Search in sources :

Example 1 with ShardLock

use of org.elasticsearch.env.ShardLock in project elasticsearch by elastic.

the class IndicesService method processPendingDeletes.

/**
     * Processes all pending deletes for the given index. This method will acquire all locks for the given index and will
     * process all pending deletes for this index. Pending deletes might occur if the OS doesn't allow deletion of files because
     * they are used by a different process ie. on Windows where files might still be open by a virus scanner. On a shared
     * filesystem a replica might not have been closed when the primary is deleted causing problems on delete calls so we
     * schedule there deletes later.
     * @param index the index to process the pending deletes for
     * @param timeout the timeout used for processing pending deletes
     */
@Override
public void processPendingDeletes(Index index, IndexSettings indexSettings, TimeValue timeout) throws IOException, InterruptedException, ShardLockObtainFailedException {
    logger.debug("{} processing pending deletes", index);
    final long startTimeNS = System.nanoTime();
    final List<ShardLock> shardLocks = nodeEnv.lockAllForIndex(index, indexSettings, timeout.millis());
    int numRemoved = 0;
    try {
        Map<ShardId, ShardLock> locks = new HashMap<>();
        for (ShardLock lock : shardLocks) {
            locks.put(lock.getShardId(), lock);
        }
        final List<PendingDelete> remove;
        synchronized (pendingDeletes) {
            remove = pendingDeletes.remove(index);
        }
        if (remove != null && remove.isEmpty() == false) {
            numRemoved = remove.size();
            // make sure we delete indices first
            CollectionUtil.timSort(remove);
            // ensure we retry after 10 sec
            final long maxSleepTimeMs = 10 * 1000;
            long sleepTime = 10;
            do {
                if (remove.isEmpty()) {
                    break;
                }
                Iterator<PendingDelete> iterator = remove.iterator();
                while (iterator.hasNext()) {
                    PendingDelete delete = iterator.next();
                    if (delete.deleteIndex) {
                        assert delete.shardId == -1;
                        logger.debug("{} deleting index store reason [{}]", index, "pending delete");
                        try {
                            nodeEnv.deleteIndexDirectoryUnderLock(index, indexSettings);
                            iterator.remove();
                        } catch (IOException ex) {
                            logger.debug((Supplier<?>) () -> new ParameterizedMessage("{} retry pending delete", index), ex);
                        }
                    } else {
                        assert delete.shardId != -1;
                        ShardLock shardLock = locks.get(new ShardId(delete.index, delete.shardId));
                        if (shardLock != null) {
                            try {
                                deleteShardStore("pending delete", shardLock, delete.settings);
                                iterator.remove();
                            } catch (IOException ex) {
                                logger.debug((Supplier<?>) () -> new ParameterizedMessage("{} retry pending delete", shardLock.getShardId()), ex);
                            }
                        } else {
                            logger.warn("{} no shard lock for pending delete", delete.shardId);
                            iterator.remove();
                        }
                    }
                }
                if (remove.isEmpty() == false) {
                    logger.warn("{} still pending deletes present for shards {} - retrying", index, remove.toString());
                    Thread.sleep(sleepTime);
                    // increase the sleep time gradually
                    sleepTime = Math.min(maxSleepTimeMs, sleepTime * 2);
                    logger.debug("{} schedule pending delete retry after {} ms", index, sleepTime);
                }
            } while ((System.nanoTime() - startTimeNS) < timeout.nanos());
        }
    } finally {
        IOUtils.close(shardLocks);
        if (numRemoved > 0) {
            int remainingUncompletedDeletes = numUncompletedDeletes.addAndGet(-numRemoved);
            assert remainingUncompletedDeletes >= 0;
        }
    }
}
Also used : HashMap(java.util.HashMap) IOException(java.io.IOException) ShardId(org.elasticsearch.index.shard.ShardId) Supplier(java.util.function.Supplier) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ShardLock(org.elasticsearch.env.ShardLock)

Example 2 with ShardLock

use of org.elasticsearch.env.ShardLock in project elasticsearch by elastic.

the class Store method tryOpenIndex.

/**
     * Tries to open an index for the given location. This includes reading the
     * segment infos and possible corruption markers. If the index can not
     * be opened, an exception is thrown
     */
public static void tryOpenIndex(Path indexLocation, ShardId shardId, NodeEnvironment.ShardLocker shardLocker, Logger logger) throws IOException, ShardLockObtainFailedException {
    try (ShardLock lock = shardLocker.lock(shardId, TimeUnit.SECONDS.toMillis(5));
        Directory dir = new SimpleFSDirectory(indexLocation)) {
        failIfCorrupted(dir, shardId);
        SegmentInfos segInfo = Lucene.readSegmentInfos(dir);
        logger.trace("{} loaded segment info [{}]", shardId, segInfo);
    }
}
Also used : SegmentInfos(org.apache.lucene.index.SegmentInfos) ShardLock(org.elasticsearch.env.ShardLock) SimpleFSDirectory(org.apache.lucene.store.SimpleFSDirectory) Directory(org.apache.lucene.store.Directory) SimpleFSDirectory(org.apache.lucene.store.SimpleFSDirectory) FilterDirectory(org.apache.lucene.store.FilterDirectory)

Example 3 with ShardLock

use of org.elasticsearch.env.ShardLock in project elasticsearch by elastic.

the class StoreTests method testOnCloseCallback.

public void testOnCloseCallback() throws IOException {
    final ShardId shardId = new ShardId(new Index(randomRealisticUnicodeOfCodepointLengthBetween(1, 10), "_na_"), randomIntBetween(0, 100));
    DirectoryService directoryService = new LuceneManagedDirectoryService(random());
    final AtomicInteger count = new AtomicInteger(0);
    final ShardLock lock = new DummyShardLock(shardId);
    Store store = new Store(shardId, INDEX_SETTINGS, directoryService, lock, theLock -> {
        assertEquals(shardId, theLock.getShardId());
        assertEquals(lock, theLock);
        count.incrementAndGet();
    });
    assertEquals(count.get(), 0);
    final int iters = randomIntBetween(1, 10);
    for (int i = 0; i < iters; i++) {
        store.close();
    }
    assertEquals(count.get(), 1);
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Index(org.elasticsearch.index.Index) DummyShardLock(org.elasticsearch.test.DummyShardLock) ShardLock(org.elasticsearch.env.ShardLock) DummyShardLock(org.elasticsearch.test.DummyShardLock)

Example 4 with ShardLock

use of org.elasticsearch.env.ShardLock in project elasticsearch by elastic.

the class IndexShardIT method testLockTryingToDelete.

public void testLockTryingToDelete() throws Exception {
    createIndex("test");
    ensureGreen();
    NodeEnvironment env = getInstanceFromNode(NodeEnvironment.class);
    ClusterService cs = getInstanceFromNode(ClusterService.class);
    final Index index = cs.state().metaData().index("test").getIndex();
    Path[] shardPaths = env.availableShardPaths(new ShardId(index, 0));
    logger.info("--> paths: [{}]", (Object) shardPaths);
    // Should not be able to acquire the lock because it's already open
    try {
        NodeEnvironment.acquireFSLockForPaths(IndexSettingsModule.newIndexSettings("test", Settings.EMPTY), shardPaths);
        fail("should not have been able to acquire the lock");
    } catch (LockObtainFailedException e) {
        assertTrue("msg: " + e.getMessage(), e.getMessage().contains("unable to acquire write.lock"));
    }
    // Test without the regular shard lock to assume we can acquire it
    // (worst case, meaning that the shard lock could be acquired and
    // we're green to delete the shard's directory)
    ShardLock sLock = new DummyShardLock(new ShardId(index, 0));
    try {
        env.deleteShardDirectoryUnderLock(sLock, IndexSettingsModule.newIndexSettings("test", Settings.EMPTY));
        fail("should not have been able to delete the directory");
    } catch (LockObtainFailedException e) {
        assertTrue("msg: " + e.getMessage(), e.getMessage().contains("unable to acquire write.lock"));
    }
}
Also used : Path(java.nio.file.Path) ClusterService(org.elasticsearch.cluster.service.ClusterService) NodeEnvironment(org.elasticsearch.env.NodeEnvironment) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) Index(org.elasticsearch.index.Index) DummyShardLock(org.elasticsearch.test.DummyShardLock) ShardLock(org.elasticsearch.env.ShardLock) DummyShardLock(org.elasticsearch.test.DummyShardLock)

Example 5 with ShardLock

use of org.elasticsearch.env.ShardLock in project crate by crate.

the class IndexService method createShard.

public synchronized IndexShard createShard(final ShardRouting routing, final Consumer<ShardId> globalCheckpointSyncer, final RetentionLeaseSyncer retentionLeaseSyncer) throws IOException {
    Objects.requireNonNull(retentionLeaseSyncer);
    /*
         * TODO: we execute this in parallel but it's a synced method. Yet, we might
         * be able to serialize the execution via the cluster state in the future. for now we just
         * keep it synced.
         */
    if (closed.get()) {
        throw new IllegalStateException("Can't create shard " + routing.shardId() + ", closed");
    }
    final Settings indexSettings = this.indexSettings.getSettings();
    final ShardId shardId = routing.shardId();
    boolean success = false;
    Store store = null;
    IndexShard indexShard = null;
    ShardLock lock = null;
    try {
        lock = nodeEnv.shardLock(shardId, "starting shard", TimeUnit.SECONDS.toMillis(5));
        eventListener.beforeIndexShardCreated(shardId, indexSettings);
        ShardPath path;
        try {
            path = ShardPath.loadShardPath(logger, nodeEnv, shardId, this.indexSettings.customDataPath());
        } catch (IllegalStateException ex) {
            logger.warn("{} failed to load shard path, trying to remove leftover", shardId);
            try {
                ShardPath.deleteLeftoverShardDirectory(logger, nodeEnv, lock, this.indexSettings);
                path = ShardPath.loadShardPath(logger, nodeEnv, shardId, this.indexSettings.customDataPath());
            } catch (Exception inner) {
                ex.addSuppressed(inner);
                throw ex;
            }
        }
        if (path == null) {
            // TODO: we should, instead, hold a "bytes reserved" of how large we anticipate this shard will be, e.g. for a shard
            // that's being relocated/replicated we know how large it will become once it's done copying:
            // Count up how many shards are currently on each data path:
            Map<Path, Integer> dataPathToShardCount = new HashMap<>();
            for (IndexShard shard : this) {
                Path dataPath = shard.shardPath().getRootStatePath();
                Integer curCount = dataPathToShardCount.get(dataPath);
                if (curCount == null) {
                    curCount = 0;
                }
                dataPathToShardCount.put(dataPath, curCount + 1);
            }
            path = ShardPath.selectNewPathForShard(nodeEnv, shardId, this.indexSettings, routing.getExpectedShardSize() == ShardRouting.UNAVAILABLE_EXPECTED_SHARD_SIZE ? getAvgShardSizeInBytes() : routing.getExpectedShardSize(), dataPathToShardCount);
            logger.debug("{} creating using a new path [{}]", shardId, path);
        } else {
            logger.debug("{} creating using an existing path [{}]", shardId, path);
        }
        if (shards.containsKey(shardId.id())) {
            throw new IllegalStateException(shardId + " already exists");
        }
        logger.debug("creating shard_id {}", shardId);
        Directory directory = directoryFactory.newDirectory(this.indexSettings, path);
        store = new Store(shardId, this.indexSettings, directory, lock, new StoreCloseListener(shardId, () -> eventListener.onStoreClosed(shardId)));
        eventListener.onStoreCreated(shardId);
        indexShard = new IndexShard(routing, this.indexSettings, path, store, indexCache, mapperService, engineFactory, eventListener, threadPool, bigArrays, indexingOperationListeners, () -> globalCheckpointSyncer.accept(shardId), retentionLeaseSyncer, circuitBreakerService);
        eventListener.indexShardStateChanged(indexShard, null, indexShard.state(), "shard created");
        eventListener.afterIndexShardCreated(indexShard);
        shards = newMapBuilder(shards).put(shardId.id(), indexShard).immutableMap();
        success = true;
        return indexShard;
    } catch (ShardLockObtainFailedException e) {
        throw new IOException("failed to obtain in-memory shard lock", e);
    } finally {
        if (success == false) {
            if (lock != null) {
                IOUtils.closeWhileHandlingException(lock);
            }
            closeShard("initialization failed", shardId, indexShard, store, eventListener);
        }
    }
}
Also used : Path(java.nio.file.Path) ShardPath(org.elasticsearch.index.shard.ShardPath) HashMap(java.util.HashMap) IndexShard(org.elasticsearch.index.shard.IndexShard) Store(org.elasticsearch.index.store.Store) IOException(java.io.IOException) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) ShardNotFoundException(org.elasticsearch.index.shard.ShardNotFoundException) WriteStateException(org.elasticsearch.gateway.WriteStateException) ShardLockObtainFailedException(org.elasticsearch.env.ShardLockObtainFailedException) IndexShardClosedException(org.elasticsearch.index.shard.IndexShardClosedException) IOException(java.io.IOException) ShardId(org.elasticsearch.index.shard.ShardId) ShardPath(org.elasticsearch.index.shard.ShardPath) ShardLock(org.elasticsearch.env.ShardLock) ShardLockObtainFailedException(org.elasticsearch.env.ShardLockObtainFailedException) Settings(org.elasticsearch.common.settings.Settings) Directory(org.apache.lucene.store.Directory)

Aggregations

ShardLock (org.elasticsearch.env.ShardLock)10 ShardId (org.elasticsearch.index.shard.ShardId)7 IOException (java.io.IOException)4 Path (java.nio.file.Path)4 HashMap (java.util.HashMap)4 Index (org.elasticsearch.index.Index)4 ParameterizedMessage (org.apache.logging.log4j.message.ParameterizedMessage)3 Directory (org.apache.lucene.store.Directory)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 SegmentInfos (org.apache.lucene.index.SegmentInfos)2 AlreadyClosedException (org.apache.lucene.store.AlreadyClosedException)2 FilterDirectory (org.apache.lucene.store.FilterDirectory)2 SimpleFSDirectory (org.apache.lucene.store.SimpleFSDirectory)2 ClusterService (org.elasticsearch.cluster.service.ClusterService)2 Settings (org.elasticsearch.common.settings.Settings)2 DummyShardLock (org.elasticsearch.test.DummyShardLock)2 Closeable (java.io.Closeable)1 UncheckedIOException (java.io.UncheckedIOException)1 Collections (java.util.Collections)1 Collections.emptyMap (java.util.Collections.emptyMap)1