Search in sources :

Example 1 with EventThrottler

use of voldemort.utils.EventThrottler in project voldemort by voldemort.

the class BlockingSlopPusherJob method run.

/**
     * Loop over entries in the slop table and attempt to push them to the
     * deserving server
     */
public void run() {
    // don't try to run slop pusher job when rebalancing
    if (metadataStore.getServerStateUnlocked().equals(MetadataStore.VoldemortState.REBALANCING_MASTER_SERVER)) {
        logger.error("Cannot run slop pusher job since Voldemort server is rebalancing");
        return;
    }
    logger.info("Started blocking slop pusher job at " + new Date());
    Cluster cluster = metadataStore.getCluster();
    failureDetector.getConfig().setCluster(cluster);
    Set<String> storeNames = StoreDefinitionUtils.getStoreNamesSet(metadataStore.getStoreDefList());
    ClosableIterator<Pair<ByteArray, Versioned<Slop>>> iterator = null;
    Map<Integer, Long> attemptedByNode = Maps.newHashMapWithExpectedSize(cluster.getNumberOfNodes());
    Map<Integer, Long> succeededByNode = Maps.newHashMapWithExpectedSize(cluster.getNumberOfNodes());
    long slopsPushed = 0L;
    long attemptedPushes = 0L;
    for (Node node : cluster.getNodes()) {
        attemptedByNode.put(node.getId(), 0L);
        succeededByNode.put(node.getId(), 0L);
    }
    acquireRepairPermit();
    try {
        SlopStorageEngine slopStorageEngine = storeRepo.getSlopStore();
        StorageEngine<ByteArray, Slop, byte[]> slopStore = slopStorageEngine.asSlopStore();
        EventThrottler throttler = new EventThrottler(maxWriteBytesPerSec);
        iterator = slopStore.entries();
        while (iterator.hasNext()) {
            if (Thread.interrupted())
                throw new InterruptedException("Slop pusher job cancelled");
            try {
                Pair<ByteArray, Versioned<Slop>> keyAndVal;
                try {
                    keyAndVal = iterator.next();
                } catch (Exception e) {
                    logger.error("Exception in iterator, escaping the loop ", e);
                    break;
                }
                Versioned<Slop> versioned = keyAndVal.getSecond();
                Slop slop = versioned.getValue();
                int nodeId = slop.getNodeId();
                // check for dead slops
                if (isSlopDead(cluster, storeNames, versioned.getValue())) {
                    handleDeadSlop(slopStorageEngine, keyAndVal);
                    // the next slop.
                    continue;
                }
                Node node = cluster.getNodeById(nodeId);
                attemptedPushes++;
                if (attemptedPushes % 10000 == 0) {
                    logger.info("Attempted pushing " + attemptedPushes + " slops");
                }
                Long attempted = attemptedByNode.get(nodeId);
                attemptedByNode.put(nodeId, attempted + 1L);
                if (failureDetector.isAvailable(node)) {
                    Store<ByteArray, byte[], byte[]> store = storeRepo.getNodeStore(slop.getStoreName(), node.getId());
                    Long startNs = System.nanoTime();
                    int nBytes = 0;
                    try {
                        nBytes = slop.getKey().length();
                        if (slop.getOperation() == Operation.PUT) {
                            store.put(slop.getKey(), new Versioned<byte[]>(slop.getValue(), versioned.getVersion()), slop.getTransforms());
                            nBytes += slop.getValue().length + ((VectorClock) versioned.getVersion()).sizeInBytes() + 1;
                        } else if (slop.getOperation() == Operation.DELETE) {
                            nBytes += ((VectorClock) versioned.getVersion()).sizeInBytes() + 1;
                            store.delete(slop.getKey(), versioned.getVersion());
                        } else {
                            logger.error("Unknown slop operation: " + slop.getOperation());
                            continue;
                        }
                        failureDetector.recordSuccess(node, deltaMs(startNs));
                        slopStore.delete(slop.makeKey(), versioned.getVersion());
                        slopsPushed++;
                        // Increment succeeded
                        Long succeeded = succeededByNode.get(nodeId);
                        succeededByNode.put(nodeId, succeeded + 1L);
                        // Throttle the bytes...
                        throttler.maybeThrottle(nBytes);
                    } catch (ObsoleteVersionException e) {
                        // okay it is old, just delete it
                        slopStore.delete(slop.makeKey(), versioned.getVersion());
                        slopsPushed++;
                        // Increment succeeded
                        Long succeeded = succeededByNode.get(nodeId);
                        succeededByNode.put(nodeId, succeeded + 1L);
                        // Throttle the bytes...
                        throttler.maybeThrottle(nBytes);
                    } catch (UnreachableStoreException e) {
                        failureDetector.recordException(node, deltaMs(startNs), e);
                    }
                }
            } catch (Exception e) {
                logger.error(e, e);
            }
        }
        // Only if we reached here do we update stats
        logger.log(attemptedPushes > 0 ? Level.INFO : Level.DEBUG, "Attempted " + attemptedPushes + " hinted handoff pushes of which " + slopsPushed + " succeeded.");
        Map<Integer, Long> outstanding = Maps.newHashMapWithExpectedSize(cluster.getNumberOfNodes());
        for (int nodeId : succeededByNode.keySet()) {
            outstanding.put(nodeId, attemptedByNode.get(nodeId) - succeededByNode.get(nodeId));
        }
        slopStorageEngine.resetStats(outstanding);
    } catch (Exception e) {
        logger.error(e, e);
    } finally {
        try {
            if (iterator != null)
                iterator.close();
        } catch (Exception e) {
            logger.error("Failed to close iterator.", e);
        }
        this.repairPermits.release(this.getClass().getCanonicalName());
    }
}
Also used : Versioned(voldemort.versioning.Versioned) Node(voldemort.cluster.Node) ByteArray(voldemort.utils.ByteArray) SlopStorageEngine(voldemort.store.slop.SlopStorageEngine) UnreachableStoreException(voldemort.store.UnreachableStoreException) Pair(voldemort.utils.Pair) EventThrottler(voldemort.utils.EventThrottler) Cluster(voldemort.cluster.Cluster) Date(java.util.Date) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) UnreachableStoreException(voldemort.store.UnreachableStoreException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) Slop(voldemort.store.slop.Slop)

Example 2 with EventThrottler

use of voldemort.utils.EventThrottler in project voldemort by voldemort.

the class BaseStreamingClient method initStreamingSessions.

/**
     ** 
     * @param stores - the list of name of the stores to be streamed to
     * 
     * 
     * @param checkpointCallback - the callback that allows for the user to
     *        record the progress, up to the last event delivered. This callable
     *        would be invoked every so often internally.
     * 
     * @param recoveryCallback - the callback that allows the user to rewind the
     *        upstream to the position recorded by the last complete call on
     *        checkpointCallback whenever an exception occurs during the
     *        streaming session.
     * 
     * @param allowMerge - whether to allow for the streaming event to be merged
     *        with online writes. If not, all online writes since the completion
     *        of the last streaming session will be lost at the end of the
     *        current streaming session.
     * 
     * @param blackListedNodes - the list of Nodes not to stream to; we can
     *        probably recover them later from the replicas
     **/
@SuppressWarnings({ "unchecked", "rawtypes" })
public synchronized void initStreamingSessions(List<String> stores, Callable checkpointCallback, Callable recoveryCallback, boolean allowMerge, List<Integer> blackListedNodes) {
    logger.info("Initializing a streaming session");
    this.checkpointCallback = checkpointCallback;
    this.recoveryCallback = recoveryCallback;
    this.allowMerge = allowMerge;
    streamingresults = Executors.newFixedThreadPool(3);
    entriesProcessed = 0;
    newBatch = true;
    isMultiSession = true;
    this.throttler = new EventThrottler(THROTTLE_QPS);
    TimeUnit unit = TimeUnit.SECONDS;
    Collection<Node> nodesInCluster = adminClient.getAdminClientCluster().getNodes();
    if (blackListedNodes != null && blackListedNodes.size() > 0) {
        this.blackListedNodes = blackListedNodes;
    }
    for (Node node : nodesInCluster) {
        if (blackListedNodes != null && blackListedNodes.size() > 0) {
            if (!blackListedNodes.contains(node.getId())) {
                nodesToStream.add(node);
            }
        } else
            nodesToStream.add(node);
    }
    // socket pool
    streamingSocketPool = new SocketPool(adminClient.getAdminClientCluster().getNumberOfNodes() * MAX_STORES_PER_SESSION, (int) unit.toMillis(adminClientConfig.getAdminConnectionTimeoutSec()), (int) unit.toMillis(adminClientConfig.getAdminSocketTimeoutSec()), adminClientConfig.getAdminSocketBufferSize(), adminClientConfig.getAdminSocketKeepAlive());
    nodeIdStoreToSocketRequest = new HashMap();
    nodeIdStoreToOutputStreamRequest = new HashMap();
    nodeIdStoreToInputStreamRequest = new HashMap();
    nodeIdStoreInitialized = new HashMap();
    storeToRoutingStrategy = new HashMap();
    nodeIdStoreToSocketAndStreams = new HashMap();
    for (String store : stores) {
        addStoreToSession(store);
    }
}
Also used : HashMap(java.util.HashMap) Node(voldemort.cluster.Node) EventThrottler(voldemort.utils.EventThrottler) TimeUnit(java.util.concurrent.TimeUnit)

Example 3 with EventThrottler

use of voldemort.utils.EventThrottler in project voldemort by voldemort.

the class DataCleanupJob method run.

@Override
public void run() {
    // if the server is neither normal nor offline , skip this run.
    if (!isServerInNormalState() && !isServerInOfflineState()) {
        return;
    }
    StoreDefinition storeDef = null;
    try {
        storeDef = MetadataStore.getStoreDef(storeName, metadataStore);
    } catch (VoldemortException ex) {
        logger.info("Error retrieving store " + storeName + " for data cleanup job ", ex);
        return;
    }
    Integer retentionDays = storeDef.getRetentionDays();
    if (retentionDays == null || retentionDays <= 0) {
        logger.info("Store " + storeName + " does not have retention period set, skipping cleanup job . RetentionDays " + retentionDays);
        return;
    }
    long maxAgeMs = retentionDays * Time.MS_PER_DAY;
    logger.info("Store " + storeName + " cleanup job is starting with RetentionDays " + retentionDays);
    acquireCleanupPermit(scanProgressThisRun, deleteProgressThisRun);
    ClosableIterator<Pair<K, Versioned<V>>> iterator = null;
    try {
        int maxReadRate = storeDef.hasRetentionScanThrottleRate() ? storeDef.getRetentionScanThrottleRate() : Integer.MAX_VALUE;
        EventThrottler throttler = new EventThrottler(maxReadRate);
        store.beginBatchModifications();
        logger.info("Starting data cleanup on store \"" + store.getName() + "\"...");
        long now = time.getMilliseconds();
        iterator = store.entries();
        while (iterator.hasNext()) {
            // check if we have been interrupted
            if (Thread.currentThread().isInterrupted()) {
                logger.info("Datacleanup job halted.");
                return;
            }
            final long INETERVAL = 10000;
            long entriesScanned = scanProgressThisRun.get();
            if (entriesScanned % INETERVAL == 0) {
                if (!isServerInNormalState() && !isServerInOfflineState()) {
                    return;
                }
            }
            scanProgressThisRun.incrementAndGet();
            Pair<K, Versioned<V>> keyAndVal = iterator.next();
            VectorClock clock = (VectorClock) keyAndVal.getSecond().getVersion();
            if (now - clock.getTimestamp() > maxAgeMs) {
                store.delete(keyAndVal.getFirst(), clock);
                final long entriesDeleted = this.deleteProgressThisRun.incrementAndGet();
                if (logger.isDebugEnabled() && entriesDeleted % INETERVAL == 0) {
                    logger.debug("Deleted item " + this.deleteProgressThisRun.get());
                }
            }
            // throttle on number of entries.
            throttler.maybeThrottle(1);
        }
        // log the total items scanned, so we will get an idea of data
        // growth in a cheap, periodic way
        logger.info("Data cleanup on store \"" + store.getName() + "\" is complete; " + this.deleteProgressThisRun.get() + " items deleted. " + scanProgressThisRun.get() + " items scanned");
    } catch (Exception e) {
        logger.error("Error in data cleanup job for store " + store.getName() + ": ", e);
    } finally {
        closeIterator(iterator);
        logger.info("Releasing lock  after data cleanup on \"" + store.getName() + "\".");
        this.cleanupPermits.release(this.getClass().getCanonicalName());
        synchronized (this) {
            totalEntriesScanned += scanProgressThisRun.get();
            scanProgressThisRun.set(0);
            totalEntriesDeleted += deleteProgressThisRun.get();
            deleteProgressThisRun.set(0);
        }
        store.endBatchModifications();
    }
}
Also used : Versioned(voldemort.versioning.Versioned) VectorClock(voldemort.versioning.VectorClock) EventThrottler(voldemort.utils.EventThrottler) VoldemortException(voldemort.VoldemortException) VoldemortException(voldemort.VoldemortException) StoreDefinition(voldemort.store.StoreDefinition) Pair(voldemort.utils.Pair)

Example 4 with EventThrottler

use of voldemort.utils.EventThrottler in project voldemort by voldemort.

the class BaseStreamingClient method updateThrottleLimit.

public synchronized void updateThrottleLimit(int throttleQPS) {
    THROTTLE_QPS = throttleQPS;
    this.throttler = new EventThrottler(THROTTLE_QPS);
}
Also used : EventThrottler(voldemort.utils.EventThrottler)

Example 5 with EventThrottler

use of voldemort.utils.EventThrottler in project voldemort by voldemort.

the class AdminServiceRequestHandler method handleFetchAndUpdate.

public VAdminProto.AsyncOperationStatusResponse handleFetchAndUpdate(VAdminProto.InitiateFetchAndUpdateRequest request) {
    final int nodeId = request.getNodeId();
    final List<Integer> partitionIds = request.getPartitionIdsList();
    final VoldemortFilter filter = request.hasFilter() ? getFilterFromRequest(request.getFilter(), voldemortConfig, networkClassLoader) : new DefaultVoldemortFilter();
    final String storeName = request.getStore();
    final Cluster initialCluster = request.hasInitialCluster() ? new ClusterMapper().readCluster(new StringReader(request.getInitialCluster())) : null;
    int requestId = asyncService.getUniqueRequestId();
    VAdminProto.AsyncOperationStatusResponse.Builder response = VAdminProto.AsyncOperationStatusResponse.newBuilder().setRequestId(requestId).setComplete(false).setDescription("Fetch and update").setStatus("Started");
    final StoreDefinition storeDef = metadataStore.getStoreDef(storeName);
    final boolean isReadOnlyStore = storeDef.getType().compareTo(ReadOnlyStorageConfiguration.TYPE_NAME) == 0;
    final StreamingStats streamingStats = voldemortConfig.isJmxEnabled() ? storeRepository.getStreamingStats(storeName) : null;
    try {
        asyncService.submitOperation(requestId, new AsyncOperation(requestId, "Fetch and Update") {

            private final AtomicBoolean running = new AtomicBoolean(true);

            @Override
            public void stop() {
                running.set(false);
                logger.info("Stopping fetch and update for store " + storeName + " from node " + nodeId + "( " + partitionIds + " )");
            }

            @Override
            public void operate() {
                AdminClient adminClient = AdminClient.createTempAdminClient(voldemortConfig, metadataStore.getCluster(), voldemortConfig.getClientMaxConnectionsPerNode());
                try {
                    StorageEngine<ByteArray, byte[], byte[]> storageEngine = getStorageEngine(storeRepository, storeName);
                    EventThrottler throttler = new EventThrottler(voldemortConfig.getStreamMaxWriteBytesPerSec());
                    if (isReadOnlyStore) {
                        ReadOnlyStorageEngine readOnlyStorageEngine = ((ReadOnlyStorageEngine) storageEngine);
                        String destinationDir = readOnlyStorageEngine.getCurrentDirPath();
                        logger.info("Fetching files for RO store '" + storeName + "' from node " + nodeId + " ( " + partitionIds + " )");
                        updateStatus("Fetching files for RO store '" + storeName + "' from node " + nodeId + " ( " + partitionIds + " )");
                        adminClient.readonlyOps.fetchPartitionFiles(nodeId, storeName, partitionIds, destinationDir, readOnlyStorageEngine.getChunkedFileSet().getChunkIdToNumChunks().keySet(), running);
                    } else {
                        logger.info("Fetching entries for RW store '" + storeName + "' from node " + nodeId + " ( " + partitionIds + " )");
                        updateStatus("Fetching entries for RW store '" + storeName + "' from node " + nodeId + " ( " + partitionIds + " ) ");
                        if (partitionIds.size() > 0) {
                            Iterator<Pair<ByteArray, Versioned<byte[]>>> entriesIterator = adminClient.bulkFetchOps.fetchEntries(nodeId, storeName, partitionIds, filter, false, initialCluster, 0);
                            long numTuples = 0;
                            long startTime = System.currentTimeMillis();
                            long startNs = System.nanoTime();
                            while (running.get() && entriesIterator.hasNext()) {
                                Pair<ByteArray, Versioned<byte[]>> entry = entriesIterator.next();
                                if (streamingStats != null) {
                                    streamingStats.reportNetworkTime(Operation.UPDATE_ENTRIES, Utils.elapsedTimeNs(startNs, System.nanoTime()));
                                }
                                ByteArray key = entry.getFirst();
                                Versioned<byte[]> value = entry.getSecond();
                                startNs = System.nanoTime();
                                try {
                                    /**
                                         * TODO This also needs to be fixed to
                                         * use the atomic multi version puts
                                         */
                                    storageEngine.put(key, value, null);
                                } catch (ObsoleteVersionException e) {
                                    // log and ignore
                                    if (logger.isDebugEnabled()) {
                                        logger.debug("Fetch and update threw Obsolete version exception. Ignoring");
                                    }
                                } finally {
                                    if (streamingStats != null) {
                                        streamingStats.reportStreamingPut(Operation.UPDATE_ENTRIES);
                                        streamingStats.reportStorageTime(Operation.UPDATE_ENTRIES, Utils.elapsedTimeNs(startNs, System.nanoTime()));
                                    }
                                }
                                long totalTime = (System.currentTimeMillis() - startTime) / 1000;
                                throttler.maybeThrottle(key.length() + valueSize(value));
                                if ((numTuples % 100000) == 0 && numTuples > 0) {
                                    logger.info(numTuples + " entries copied from node " + nodeId + " for store '" + storeName + "' in " + totalTime + " seconds");
                                    updateStatus(numTuples + " entries copied from node " + nodeId + " for store '" + storeName + "' in " + totalTime + " seconds");
                                }
                                numTuples++;
                            }
                            long totalTime = (System.currentTimeMillis() - startTime) / 1000;
                            if (running.get()) {
                                logger.info("Completed fetching " + numTuples + " entries from node " + nodeId + " for store '" + storeName + "' in " + totalTime + " seconds");
                            } else {
                                logger.info("Fetch and update stopped after fetching " + numTuples + " entries for node " + nodeId + " for store '" + storeName + "' in " + totalTime + " seconds");
                            }
                        } else {
                            logger.info("No entries to fetch from node " + nodeId + " for store '" + storeName + "'");
                        }
                    }
                } finally {
                    adminClient.close();
                }
            }
        });
    } catch (VoldemortException e) {
        response.setError(ProtoUtils.encodeError(errorCodeMapper, e));
        logger.error("handleFetchAndUpdate failed for request(" + request.toString() + ")", e);
    }
    return response.build();
}
Also used : Versioned(voldemort.versioning.Versioned) MysqlStorageEngine(voldemort.store.mysql.MysqlStorageEngine) StorageEngine(voldemort.store.StorageEngine) SlopStorageEngine(voldemort.store.slop.SlopStorageEngine) ReadOnlyStorageEngine(voldemort.store.readonly.ReadOnlyStorageEngine) DefaultVoldemortFilter(voldemort.client.protocol.admin.filter.DefaultVoldemortFilter) VoldemortFilter(voldemort.client.protocol.VoldemortFilter) VoldemortException(voldemort.VoldemortException) StreamingStats(voldemort.store.stats.StreamingStats) StoreDefinition(voldemort.store.StoreDefinition) StringReader(java.io.StringReader) ClosableIterator(voldemort.utils.ClosableIterator) Iterator(java.util.Iterator) ByteArray(voldemort.utils.ByteArray) Pair(voldemort.utils.Pair) EventThrottler(voldemort.utils.EventThrottler) Cluster(voldemort.cluster.Cluster) ReadOnlyStorageEngine(voldemort.store.readonly.ReadOnlyStorageEngine) ClusterMapper(voldemort.xml.ClusterMapper) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) DefaultVoldemortFilter(voldemort.client.protocol.admin.filter.DefaultVoldemortFilter) AdminClient(voldemort.client.protocol.admin.AdminClient)

Aggregations

EventThrottler (voldemort.utils.EventThrottler)6 Pair (voldemort.utils.Pair)4 Versioned (voldemort.versioning.Versioned)4 VoldemortException (voldemort.VoldemortException)3 ByteArray (voldemort.utils.ByteArray)3 StringReader (java.io.StringReader)2 VoldemortFilter (voldemort.client.protocol.VoldemortFilter)2 DefaultVoldemortFilter (voldemort.client.protocol.admin.filter.DefaultVoldemortFilter)2 Cluster (voldemort.cluster.Cluster)2 Node (voldemort.cluster.Node)2 StoreDefinition (voldemort.store.StoreDefinition)2 SlopStorageEngine (voldemort.store.slop.SlopStorageEngine)2 ObsoleteVersionException (voldemort.versioning.ObsoleteVersionException)2 ClusterMapper (voldemort.xml.ClusterMapper)2 Date (java.util.Date)1 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 TimeUnit (java.util.concurrent.TimeUnit)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AdminClient (voldemort.client.protocol.admin.AdminClient)1