Search in sources :

Example 26 with VoldemortException

use of voldemort.VoldemortException in project voldemort by voldemort.

the class AdminStoreSwapper method invokeFetch.

public Map<Node, Response> invokeFetch(final String storeName, final String basePath, final long pushVersion) {
    // do fetch
    final Map<Integer, Future<String>> fetchDirs = new HashMap<Integer, Future<String>>();
    for (final Node node : cluster.getNodes()) {
        fetchDirs.put(node.getId(), executor.submit(new Callable<String>() {

            public String call() throws Exception {
                String response = null;
                if (buildPrimaryReplicasOnly) {
                    // Then we give the root directory to the server and let it decide what to fetch
                    response = fetch(basePath);
                } else {
                    // Old behavior: fetch the node directory only
                    String storeDir = basePath + "/" + ReadOnlyUtils.NODE_DIRECTORY_PREFIX + node.getId();
                    response = fetch(storeDir);
                }
                if (response == null)
                    throw new VoldemortException("Fetch request on " + node.briefToString() + " failed");
                logger.info("Fetch succeeded on " + node.briefToString());
                return response.trim();
            }

            private String fetch(String hadoopStoreDirToFetch) {
                // We need to keep the AdminClient instance separate in each Callable, so that a refresh of
                // the client in one callable does not refresh the AdminClient used by another callable.
                AdminClient currentAdminClient = AdminStoreSwapper.this.adminClient;
                int attempt = 1;
                while (attempt <= MAX_FETCH_ATTEMPTS) {
                    if (attempt > 1) {
                        logger.info("Fetch attempt " + attempt + "/" + MAX_FETCH_ATTEMPTS + " for " + node.briefToString() + ". Will wait " + WAIT_TIME_BETWEEN_FETCH_ATTEMPTS + " ms before going ahead.");
                        try {
                            Thread.sleep(WAIT_TIME_BETWEEN_FETCH_ATTEMPTS);
                        } catch (InterruptedException e) {
                            throw new VoldemortException(e);
                        }
                    }
                    logger.info("Invoking fetch for " + node.briefToString() + " for " + hadoopStoreDirToFetch);
                    try {
                        return currentAdminClient.readonlyOps.fetchStore(node.getId(), storeName, hadoopStoreDirToFetch, pushVersion, timeoutMs);
                    } catch (AsyncOperationTimeoutException e) {
                        throw e;
                    } catch (VoldemortException ve) {
                        if (attempt >= MAX_FETCH_ATTEMPTS) {
                            throw ve;
                        }
                        if (ExceptionUtils.recursiveClassEquals(ve, ExceptionUtils.BNP_SOFT_ERRORS)) {
                            String logMessage = "Got a " + ve.getClass().getSimpleName() + " from " + node.briefToString() + " while trying to fetch store '" + storeName + "'" + " (attempt " + attempt + "/" + MAX_FETCH_ATTEMPTS + ").";
                            if (currentAdminClient.isClusterModified()) {
                                logMessage += " It seems like the cluster.xml state has changed since this" + " AdminClient was constructed. Therefore, we will attempt constructing" + " a fresh AdminClient and retrying the fetch operation.";
                                currentAdminClient = currentAdminClient.getFreshClient();
                            } else {
                                logMessage += " The cluster.xml is up to date. We will retry with the same AdminClient.";
                            }
                            logger.info(logMessage);
                            attempt++;
                        } else {
                            throw ve;
                        }
                    }
                }
                // Defensive coding
                throw new IllegalStateException("Code should never reach here!");
            }
        }));
    }
    Map<Node, Response> fetchResponseMap = Maps.newTreeMap();
    boolean fetchErrors = false;
    /*
         * We wait for all fetches to complete successfully or throw any
         * Exception. We don't handle QuotaException in a special way here. The
         * idea is to protect the disk. It is okay to let the Bnp job run to
         * completion. We still want to delete data of a failed fetch in all
         * nodes that successfully fetched the data. After deleting the
         * failedFetch data, we bubble up the Quota Exception as needed.
         * 
         * The alternate is to cancel all future tasks as soon as we detect a
         * QuotaExceededException. This will save time (fail faster) and protect
         * the disk usage. But does not guarantee a clean state in all nodes wrt
         * to data from failed fetch. Someone manually needs to clean up all the
         * data from failedFetches. Instead we try to cleanup the data as much
         * as we can before we fail the job.
         * 
         * In iteration 2 we can try to improve this to fail faster, by adding
         * either/both:
         * 
         * 1. Client side checks 2. Server side takes care of failing fast as
         * soon as it detect QuotaExceededException in one of the servers. Note
         * that this needs careful decision on how to handle those fetches that
         * already started in other nodes and how & when to clean them up.
         */
    ArrayList<Node> failedNodes = new ArrayList<Node>();
    for (final Node node : cluster.getNodes()) {
        Future<String> val = fetchDirs.get(node.getId());
        try {
            String response = val.get();
            fetchResponseMap.put(node, new Response(response));
        } catch (Exception e) {
            if (e.getCause() instanceof UnauthorizedStoreException) {
                throw (UnauthorizedStoreException) e.getCause();
            } else {
                fetchErrors = true;
                fetchResponseMap.put(node, new Response(e));
                failedNodes.add(node);
            }
        }
    }
    if (fetchErrors) {
        // Log All the errors for the user
        for (Map.Entry<Node, Response> entry : fetchResponseMap.entrySet()) {
            if (!entry.getValue().isSuccessful()) {
                logger.error("Error on " + entry.getKey().briefToString() + " during push : ", entry.getValue().getException());
            }
        }
        Iterator<FailedFetchStrategy> strategyIterator = failedFetchStrategyList.iterator();
        boolean swapIsPossible = false;
        FailedFetchStrategy strategy = null;
        while (strategyIterator.hasNext() && !swapIsPossible) {
            strategy = strategyIterator.next();
            try {
                logger.info("About to attempt: " + strategy.toString());
                swapIsPossible = strategy.dealWithIt(storeName, pushVersion, fetchResponseMap);
                logger.info("Finished executing: " + strategy.toString() + "; swapIsPossible: " + swapIsPossible);
            } catch (Exception e) {
                if (strategyIterator.hasNext()) {
                    logger.error("Got an exception while trying to execute: " + strategy.toString() + ". Continuing with next strategy.", e);
                } else {
                    logger.error("Got an exception while trying to execute the last remaining strategy: " + strategy.toString() + ". Swap will be aborted.", e);
                }
            }
        }
        if (!swapIsPossible) {
            throw new VoldemortException("Exception during push. Swap will be aborted", fetchResponseMap.get(failedNodes.get(0)).getException());
        }
    }
    return fetchResponseMap;
}
Also used : UnauthorizedStoreException(voldemort.store.readonly.UnauthorizedStoreException) HashMap(java.util.HashMap) Node(voldemort.cluster.Node) ArrayList(java.util.ArrayList) VoldemortException(voldemort.VoldemortException) Callable(java.util.concurrent.Callable) AsyncOperationTimeoutException(voldemort.client.protocol.admin.AsyncOperationTimeoutException) AsyncOperationTimeoutException(voldemort.client.protocol.admin.AsyncOperationTimeoutException) UnauthorizedStoreException(voldemort.store.readonly.UnauthorizedStoreException) VoldemortException(voldemort.VoldemortException) Future(java.util.concurrent.Future) HashMap(java.util.HashMap) Map(java.util.Map) AdminClient(voldemort.client.protocol.admin.AdminClient)

Example 27 with VoldemortException

use of voldemort.VoldemortException in project voldemort by voldemort.

the class AdminStoreSwapper method invokeRollback.

public void invokeRollback(final String storeName, final long pushVersion) {
    Exception exception = null;
    for (Node node : cluster.getNodes()) {
        try {
            logger.info("Attempting rollback for " + node.briefToString() + ", storeName = " + storeName);
            adminClient.readonlyOps.rollbackStore(node.getId(), storeName, pushVersion);
            logger.info("Rollback succeeded for " + node.briefToString());
        } catch (Exception e) {
            exception = e;
            logger.error("Exception thrown during rollback operation on " + node.briefToString(), e);
        }
    }
    if (exception != null)
        throw new VoldemortException(exception);
}
Also used : Node(voldemort.cluster.Node) VoldemortException(voldemort.VoldemortException) AsyncOperationTimeoutException(voldemort.client.protocol.admin.AsyncOperationTimeoutException) UnauthorizedStoreException(voldemort.store.readonly.UnauthorizedStoreException) VoldemortException(voldemort.VoldemortException)

Example 28 with VoldemortException

use of voldemort.VoldemortException in project voldemort by voldemort.

the class ExternalSorter method sorted.

/**
     * Produce an iterator over the input values in sorted order. Sorting will
     * occur in the fixed space configured in the constructor, data will be
     * dumped to disk as necessary.
     * 
     * @param input An iterator over the input values
     * @return An iterator over the values
     */
public Iterable<V> sorted(Iterator<V> input) {
    ExecutorService executor = new ThreadPoolExecutor(this.numThreads, this.numThreads, 1000L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new CallerRunsPolicy());
    final AtomicInteger count = new AtomicInteger(0);
    final List<File> tempFiles = Collections.synchronizedList(new ArrayList<File>());
    while (input.hasNext()) {
        final int segmentId = count.getAndIncrement();
        final long segmentStartMs = System.currentTimeMillis();
        logger.info("Segment " + segmentId + ": filling sort buffer for segment...");
        @SuppressWarnings("unchecked") final V[] buffer = (V[]) new Object[internalSortSize];
        int segmentSizeIter = 0;
        for (; segmentSizeIter < internalSortSize && input.hasNext(); segmentSizeIter++) buffer[segmentSizeIter] = input.next();
        final int segmentSize = segmentSizeIter;
        logger.info("Segment " + segmentId + ": sort buffer filled...adding to sort queue.");
        // sort and write out asynchronously
        executor.execute(new Runnable() {

            public void run() {
                logger.info("Segment " + segmentId + ": sorting buffer.");
                long start = System.currentTimeMillis();
                Arrays.sort(buffer, 0, segmentSize, comparator);
                long elapsed = System.currentTimeMillis() - start;
                logger.info("Segment " + segmentId + ": sort completed in " + elapsed + " ms, writing to temp file.");
                // write out values to a temp file
                try {
                    File tempFile = File.createTempFile("segment-", ".dat", tempDir);
                    tempFile.deleteOnExit();
                    tempFiles.add(tempFile);
                    OutputStream os = new BufferedOutputStream(new FileOutputStream(tempFile), bufferSize);
                    if (gzip)
                        os = new GZIPOutputStream(os);
                    DataOutputStream output = new DataOutputStream(os);
                    for (int i = 0; i < segmentSize; i++) writeValue(output, buffer[i]);
                    output.close();
                } catch (IOException e) {
                    throw new VoldemortException(e);
                }
                long segmentElapsed = System.currentTimeMillis() - segmentStartMs;
                logger.info("Segment " + segmentId + ": completed processing of segment in " + segmentElapsed + " ms.");
            }
        });
    }
    // wait for all sorting to complete
    executor.shutdown();
    try {
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
        // create iterator over sorted values
        return new DefaultIterable<V>(new ExternalSorterIterator(tempFiles, bufferSize / tempFiles.size()));
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}
Also used : CallerRunsPolicy(java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy) DataOutputStream(java.io.DataOutputStream) BufferedOutputStream(java.io.BufferedOutputStream) DataOutputStream(java.io.DataOutputStream) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) GZIPOutputStream(java.util.zip.GZIPOutputStream) VoldemortException(voldemort.VoldemortException) GZIPOutputStream(java.util.zip.GZIPOutputStream) DefaultIterable(voldemort.utils.DefaultIterable) BufferedOutputStream(java.io.BufferedOutputStream) IOException(java.io.IOException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) FileOutputStream(java.io.FileOutputStream) ExecutorService(java.util.concurrent.ExecutorService) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) File(java.io.File)

Example 29 with VoldemortException

use of voldemort.VoldemortException in project voldemort by voldemort.

the class ExternalSorter method readValue.

private V readValue(DataInputStream stream) throws EOFException {
    try {
        int size = stream.readInt();
        byte[] bytes = new byte[size];
        ByteUtils.read(stream, bytes);
        return serializer.toObject(bytes);
    } catch (EOFException e) {
        throw e;
    } catch (IOException e) {
        throw new VoldemortException(e);
    }
}
Also used : EOFException(java.io.EOFException) IOException(java.io.IOException) VoldemortException(voldemort.VoldemortException)

Example 30 with VoldemortException

use of voldemort.VoldemortException in project voldemort by voldemort.

the class ReadOnlyStorageEngine method swapFiles.

/**
     * Swap the current version folder for a new one
     * 
     * @param newStoreDirectory The path to the new version directory
     */
@JmxOperation(description = "swapFiles changes this store to use the new data directory")
public void swapFiles(String newStoreDirectory) {
    logger.info("Swapping files for store '" + getName() + "' to " + newStoreDirectory);
    File newVersionDir = new File(newStoreDirectory);
    if (!newVersionDir.exists())
        throw new VoldemortException("File " + newVersionDir.getAbsolutePath() + " does not exist.");
    if (!(newVersionDir.getParentFile().compareTo(storeDir.getAbsoluteFile()) == 0 && ReadOnlyUtils.checkVersionDirName(newVersionDir)))
        throw new VoldemortException("Invalid version folder name '" + newVersionDir + "'. Either parent directory is incorrect or format(version-n) is incorrect");
    // retrieve previous version for (a) check if last write is winning
    // (b) if failure, rollback use
    File previousVersionDir = ReadOnlyUtils.getCurrentVersion(storeDir);
    if (previousVersionDir == null)
        throw new VoldemortException("Could not find any latest directory to swap with in store '" + getName() + "'");
    long newVersionId = ReadOnlyUtils.getVersionId(newVersionDir);
    long previousVersionId = ReadOnlyUtils.getVersionId(previousVersionDir);
    if (newVersionId == -1 || previousVersionId == -1)
        throw new VoldemortException("Unable to parse folder names (" + newVersionDir.getName() + "," + previousVersionDir.getName() + ") since format(version-n) is incorrect");
    // check if we're greater than latest since we want last write to win
    if (previousVersionId > newVersionId) {
        logger.info("No swap required since current latest version " + previousVersionId + " is greater than swap version " + newVersionId);
        deleteBackups();
        return;
    }
    logger.info("Acquiring write lock on '" + getName() + "':");
    fileModificationLock.writeLock().lock();
    boolean success = false;
    try {
        close();
        logger.info("Opening primary files for store '" + getName() + "' at " + newStoreDirectory);
        // open the latest store
        open(newVersionDir);
        success = true;
    } finally {
        try {
            // we failed to do the swap, attempt a rollback to last version
            if (!success)
                rollback(previousVersionDir);
        } finally {
            fileModificationLock.writeLock().unlock();
            if (success)
                logger.info("Swap operation completed successfully on store " + getName() + ", releasing lock.");
            else
                logger.error("Swap operation failed.");
        }
    }
    // okay we have released the lock and the store is now open again, it is
    // safe to do a potentially slow delete if we have one too many backups
    deleteBackups();
}
Also used : File(java.io.File) VoldemortException(voldemort.VoldemortException) JmxOperation(voldemort.annotations.jmx.JmxOperation)

Aggregations

VoldemortException (voldemort.VoldemortException)247 IOException (java.io.IOException)63 ByteArray (voldemort.utils.ByteArray)52 File (java.io.File)46 Node (voldemort.cluster.Node)42 StoreDefinition (voldemort.store.StoreDefinition)39 Versioned (voldemort.versioning.Versioned)38 ArrayList (java.util.ArrayList)34 Test (org.junit.Test)30 ObsoleteVersionException (voldemort.versioning.ObsoleteVersionException)26 List (java.util.List)21 HashMap (java.util.HashMap)20 Cluster (voldemort.cluster.Cluster)20 VectorClock (voldemort.versioning.VectorClock)16 NoSuchCapabilityException (voldemort.store.NoSuchCapabilityException)15 ReadOnlyStorageEngine (voldemort.store.readonly.ReadOnlyStorageEngine)14 ExecutionException (java.util.concurrent.ExecutionException)13 StoreDefinitionsMapper (voldemort.xml.StoreDefinitionsMapper)13 Map (java.util.Map)12 Path (org.apache.hadoop.fs.Path)12