Package com.thinkaurelius.titan.diskstorage.util

Source Code of com.thinkaurelius.titan.diskstorage.util.BackendOperation

package com.thinkaurelius.titan.diskstorage.util;

import com.google.common.base.Preconditions;
import com.thinkaurelius.titan.core.TitanException;
import com.thinkaurelius.titan.diskstorage.StorageException;
import com.thinkaurelius.titan.diskstorage.TemporaryStorageException;
import com.thinkaurelius.titan.diskstorage.keycolumnvalue.StoreTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Callable;

/**
* @author Matthias Broecheler (me@matthiasb.com)
*/

public class BackendOperation {

    private static final Logger log =
            LoggerFactory.getLogger(BackendOperation.class);

    private static final long BASE_REATTEMPT_TIME_MS=50;

    public static final<V> V execute(Callable<V> exe, long maxTimeMS) throws TitanException {
        long waitTime = BASE_REATTEMPT_TIME_MS;
        long maxTime = System.currentTimeMillis()+maxTimeMS;
        StorageException lastException = null;
        do {
            try {
                return exe.call();
            } catch (StorageException e) {
                if (e instanceof TemporaryStorageException) lastException = e;
                else throw new TitanException("Permanent exception during backend operation",e); //Its permanent
            } catch (Throwable e) {
                throw new TitanException("Unexpected exception during backend operation",e);
            }
            //Wait and retry
            Preconditions.checkNotNull(lastException);
            if (System.currentTimeMillis()+waitTime<maxTime) {
                log.info("Temporary storage exception during backend operation. Attempting backoff retry",exe.toString(),lastException);
                try {
                    Thread.sleep(waitTime);
                } catch (InterruptedException r) {
                    throw new TitanException("Interrupted while waiting to retry failed storage operation", r);
                }
            }
            waitTime*=2; //Exponential backoff
        } while (System.currentTimeMillis()<maxTime);
        throw new TitanException("Could not successfully complete backend operation due to repeated temporary exceptions after "+maxTimeMS+" ms",lastException);
    }

    private static final double WAITTIME_PERTURBATION_PERCENTAGE = 0.5;
    private static final double WAITTIME_PERTURBATION_PERCENTAGE_HALF = WAITTIME_PERTURBATION_PERCENTAGE/2;

    public static final<V> V execute(Callable<V> exe, int maxRetryAttempts, long retryWaittime) throws TitanException {
        Preconditions.checkArgument(maxRetryAttempts>0,"Retry attempts must be positive");
        Preconditions.checkArgument(retryWaittime>=0,"Retry wait time must be non-negative");
        int retryAttempts = 0;
        StorageException lastException = null;
        do {
            try {
                return exe.call();
            } catch (StorageException e) {
                if (e instanceof TemporaryStorageException) lastException = e;
                else throw new TitanException("Permanent exception during backend operation",e); //Its permanent
            } catch (Throwable e) {
                throw new TitanException("Unexpected exception during backend operation",e);
            }
            //Wait and retry
            retryAttempts++;
            Preconditions.checkNotNull(lastException);
            if (retryAttempts<maxRetryAttempts) {
                long waitTime = Math.round(retryWaittime+((Math.random()*WAITTIME_PERTURBATION_PERCENTAGE-WAITTIME_PERTURBATION_PERCENTAGE_HALF)*retryWaittime));
                Preconditions.checkArgument(waitTime>=0,"Invalid wait time: %s",waitTime);
                log.info("Temporary storage exception during backend operation [{}]. Attempting incremental retry",exe.toString(),lastException);
                try {
                    Thread.sleep(waitTime);
                } catch (InterruptedException r) {
                    throw new TitanException("Interrupted while waiting to retry failed backend operation", r);
                }
            }
        } while (retryAttempts<maxRetryAttempts);
        throw new TitanException("Could not successfully complete backend operation due to repeated temporary exceptions after "+maxRetryAttempts+" attempts",lastException);
    }

    public static<R> R execute(Transactional<R> exe, TransactionalProvider provider) throws StorageException {
        StoreTransaction txh = null;
        try {
            txh = provider.openTx();
            return exe.call(txh);
        } catch (StorageException e) {
            if (txh!=null) txh.rollback();
            txh=null;
            throw e;
        } finally {
            if (txh!=null) txh.commit();
        }
    }


    public static interface Transactional<R> {

        public R call(StoreTransaction txh) throws StorageException;

    }

    public static interface TransactionalProvider {

        public StoreTransaction openTx() throws StorageException;

    }

}
TOP

Related Classes of com.thinkaurelius.titan.diskstorage.util.BackendOperation

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.