Search in sources :

Example 36 with ReleasableLock

use of org.elasticsearch.common.util.concurrent.ReleasableLock in project elasticsearch by elastic.

the class InternalEngine method delete.

@Override
public DeleteResult delete(Delete delete) throws IOException {
    DeleteResult result;
    try (ReleasableLock ignored = readLock.acquire()) {
        assert assertVersionType(delete);
        ensureOpen();
        // NOTE: we don't throttle this when merges fall behind because delete-by-id does not create new segments:
        result = innerDelete(delete);
    } catch (RuntimeException | IOException e) {
        try {
            maybeFailEngine("index", e);
        } catch (Exception inner) {
            e.addSuppressed(inner);
        }
        throw e;
    }
    maybePruneDeletedTombstones();
    return result;
}
Also used : IOException(java.io.IOException) ReleasableLock(org.elasticsearch.common.util.concurrent.ReleasableLock) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) TranslogCorruptedException(org.elasticsearch.index.translog.TranslogCorruptedException) IOException(java.io.IOException) IndexFormatTooOldException(org.apache.lucene.index.IndexFormatTooOldException)

Example 37 with ReleasableLock

use of org.elasticsearch.common.util.concurrent.ReleasableLock in project crate by crate.

the class InternalEngine method rollTranslogGeneration.

@Override
public void rollTranslogGeneration() throws EngineException {
    try (ReleasableLock ignored = readLock.acquire()) {
        ensureOpen();
        translog.rollGeneration();
        translog.trimUnreferencedReaders();
    } catch (AlreadyClosedException e) {
        failOnTragicEvent(e);
        throw e;
    } catch (Exception e) {
        try {
            failEngine("translog trimming failed", e);
        } catch (Exception inner) {
            e.addSuppressed(inner);
        }
        throw new EngineException(shardId, "failed to roll translog", e);
    }
}
Also used : AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) ReleasableLock(org.elasticsearch.common.util.concurrent.ReleasableLock) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) TranslogCorruptedException(org.elasticsearch.index.translog.TranslogCorruptedException) IOException(java.io.IOException)

Example 38 with ReleasableLock

use of org.elasticsearch.common.util.concurrent.ReleasableLock in project crate by crate.

the class InternalEngine method trimOperationsFromTranslog.

@Override
public void trimOperationsFromTranslog(long belowTerm, long aboveSeqNo) throws EngineException {
    try (ReleasableLock lock = readLock.acquire()) {
        ensureOpen();
        translog.trimOperations(belowTerm, aboveSeqNo);
    } catch (AlreadyClosedException e) {
        failOnTragicEvent(e);
        throw e;
    } catch (Exception e) {
        try {
            failEngine("translog operations trimming failed", e);
        } catch (Exception inner) {
            e.addSuppressed(inner);
        }
        throw new EngineException(shardId, "failed to trim translog operations", e);
    }
}
Also used : AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) ReleasableLock(org.elasticsearch.common.util.concurrent.ReleasableLock) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) TranslogCorruptedException(org.elasticsearch.index.translog.TranslogCorruptedException) IOException(java.io.IOException)

Example 39 with ReleasableLock

use of org.elasticsearch.common.util.concurrent.ReleasableLock in project crate by crate.

the class InternalEngine method flush.

@Override
public CommitId flush(boolean force, boolean waitIfOngoing) throws EngineException {
    ensureOpen();
    if (force && waitIfOngoing == false) {
        assert false : "wait_if_ongoing must be true for a force flush: force=" + force + " wait_if_ongoing=" + waitIfOngoing;
        throw new IllegalArgumentException("wait_if_ongoing must be true for a force flush: force=" + force + " wait_if_ongoing=" + waitIfOngoing);
    }
    final byte[] newCommitId;
    try (ReleasableLock lock = readLock.acquire()) {
        ensureOpen();
        if (flushLock.tryLock() == false) {
            // if we can't get the lock right away we block if needed otherwise barf
            if (waitIfOngoing) {
                logger.trace("waiting for in-flight flush to finish");
                flushLock.lock();
                logger.trace("acquired flush lock after blocking");
            } else {
                return new CommitId(lastCommittedSegmentInfos.getId());
            }
        } else {
            logger.trace("acquired flush lock immediately");
        }
        try {
            // Only flush if (1) Lucene has uncommitted docs, or (2) forced by caller, or (3) the
            // newly created commit points to a different translog generation (can free translog),
            // or (4) the local checkpoint information in the last commit is stale, which slows down future recoveries.
            boolean hasUncommittedChanges = indexWriter.hasUncommittedChanges();
            boolean shouldPeriodicallyFlush = shouldPeriodicallyFlush();
            if (hasUncommittedChanges || force || shouldPeriodicallyFlush || getProcessedLocalCheckpoint() > Long.parseLong(lastCommittedSegmentInfos.userData.get(SequenceNumbers.LOCAL_CHECKPOINT_KEY))) {
                ensureCanFlush();
                try {
                    translog.rollGeneration();
                    logger.trace("starting commit for flush; commitTranslog=true");
                    commitIndexWriter(indexWriter, translog, null);
                    logger.trace("finished commit for flush");
                    // we need to refresh in order to clear older version values
                    refresh("version_table_flush", SearcherScope.INTERNAL, true);
                    translog.trimUnreferencedReaders();
                } catch (AlreadyClosedException e) {
                    failOnTragicEvent(e);
                    throw e;
                } catch (Exception e) {
                    throw new FlushFailedEngineException(shardId, e);
                }
                refreshLastCommittedSegmentInfos();
            }
            newCommitId = lastCommittedSegmentInfos.getId();
        } catch (FlushFailedEngineException ex) {
            maybeFailEngine("flush", ex);
            throw ex;
        } finally {
            flushLock.unlock();
        }
    }
    // (e.g., moves backwards) we will at least still sometimes prune deleted tombstones:
    if (engineConfig.isEnableGcDeletes()) {
        pruneDeletedTombstones();
    }
    return new CommitId(newCommitId);
}
Also used : AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) ReleasableLock(org.elasticsearch.common.util.concurrent.ReleasableLock) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) TranslogCorruptedException(org.elasticsearch.index.translog.TranslogCorruptedException) IOException(java.io.IOException)

Example 40 with ReleasableLock

use of org.elasticsearch.common.util.concurrent.ReleasableLock in project crate by crate.

the class InternalEngine method index.

@Override
public IndexResult index(Index index) throws IOException {
    assert Objects.equals(index.uid().field(), IdFieldMapper.NAME) : index.uid().field();
    final boolean doThrottle = index.origin().isRecovery() == false;
    try (ReleasableLock releasableLock = readLock.acquire()) {
        ensureOpen();
        assert assertIncomingSequenceNumber(index.origin(), index.seqNo());
        try (Releasable ignored = versionMap.acquireLock(index.uid().bytes());
            Releasable indexThrottle = doThrottle ? () -> {
            } : throttle.acquireThrottle()) {
            lastWriteNanos = index.startTime();
            /* A NOTE ABOUT APPEND ONLY OPTIMIZATIONS:
                 * if we have an autoGeneratedID that comes into the engine we can potentially optimize
                 * and just use addDocument instead of updateDocument and skip the entire version and index lookupVersion across the board.
                 * Yet, we have to deal with multiple document delivery, for this we use a property of the document that is added
                 * to detect if it has potentially been added before. We use the documents timestamp for this since it's something
                 * that:
                 *  - doesn't change per document
                 *  - is preserved in the transaction log
                 *  - and is assigned before we start to index / replicate
                 * NOTE: it's not important for this timestamp to be consistent across nodes etc. it's just a number that is in the common
                 * case increasing and can be used in the failure case when we retry and resent documents to establish a happens before
                 * relationship. For instance:
                 *  - doc A has autoGeneratedIdTimestamp = 10, isRetry = false
                 *  - doc B has autoGeneratedIdTimestamp = 9, isRetry = false
                 *
                 *  while both docs are in in flight, we disconnect on one node, reconnect and send doc A again
                 *  - now doc A' has autoGeneratedIdTimestamp = 10, isRetry = true
                 *
                 *  if A' arrives on the shard first we update maxUnsafeAutoIdTimestamp to 10 and use update document. All subsequent
                 *  documents that arrive (A and B) will also use updateDocument since their timestamps are less than
                 *  maxUnsafeAutoIdTimestamp. While this is not strictly needed for doc B it is just much simpler to implement since it
                 *  will just de-optimize some doc in the worst case.
                 *
                 *  if A arrives on the shard first we use addDocument since maxUnsafeAutoIdTimestamp is < 10. A` will then just be skipped
                 *  or calls updateDocument.
                 */
            final IndexingStrategy plan = indexingStrategyForOperation(index);
            final IndexResult indexResult;
            if (plan.earlyResultOnPreFlightError.isPresent()) {
                indexResult = plan.earlyResultOnPreFlightError.get();
                assert indexResult.getResultType() == Result.Type.FAILURE : indexResult.getResultType();
            } else {
                // generate or register sequence number
                if (index.origin() == Operation.Origin.PRIMARY) {
                    index = new Index(index.uid(), index.parsedDoc(), generateSeqNoForOperationOnPrimary(index), index.primaryTerm(), index.version(), index.versionType(), index.origin(), index.startTime(), index.getAutoGeneratedIdTimestamp(), index.isRetry(), index.getIfSeqNo(), index.getIfPrimaryTerm());
                    final boolean toAppend = plan.indexIntoLucene && plan.useLuceneUpdateDocument == false;
                    if (toAppend == false) {
                        advanceMaxSeqNoOfUpdatesOrDeletesOnPrimary(index.seqNo());
                    }
                } else {
                    markSeqNoAsSeen(index.seqNo());
                }
                assert index.seqNo() >= 0 : "ops should have an assigned seq no.; origin: " + index.origin();
                if (plan.indexIntoLucene || plan.addStaleOpToLucene) {
                    indexResult = indexIntoLucene(index, plan);
                } else {
                    indexResult = new IndexResult(plan.versionForIndexing, index.primaryTerm(), index.seqNo(), plan.currentNotFoundOrDeleted);
                }
            }
            if (index.origin().isFromTranslog() == false) {
                final Translog.Location location;
                if (indexResult.getResultType() == Result.Type.SUCCESS) {
                    location = translog.add(new Translog.Index(index, indexResult));
                } else if (indexResult.getSeqNo() != SequenceNumbers.UNASSIGNED_SEQ_NO) {
                    // if we have document failure, record it as a no-op in the translog and Lucene with the generated seq_no
                    final NoOp noOp = new NoOp(indexResult.getSeqNo(), index.primaryTerm(), index.origin(), index.startTime(), indexResult.getFailure().toString());
                    location = innerNoOp(noOp).getTranslogLocation();
                } else {
                    location = null;
                }
                indexResult.setTranslogLocation(location);
            }
            if (plan.indexIntoLucene && indexResult.getResultType() == Result.Type.SUCCESS) {
                final Translog.Location translogLocation = trackTranslogLocation.get() ? indexResult.getTranslogLocation() : null;
                versionMap.maybePutIndexUnderLock(index.uid().bytes(), new IndexVersionValue(translogLocation, plan.versionForIndexing, index.seqNo(), index.primaryTerm()));
            }
            localCheckpointTracker.markSeqNoAsProcessed(indexResult.getSeqNo());
            if (indexResult.getTranslogLocation() == null) {
                // the op is coming from the translog (and is hence persisted already) or it does not have a sequence number
                assert index.origin().isFromTranslog() || indexResult.getSeqNo() == SequenceNumbers.UNASSIGNED_SEQ_NO : "version conflict: index operation not coming from translog should not have seqNo, but found [" + indexResult.getSeqNo() + "]";
                localCheckpointTracker.markSeqNoAsPersisted(indexResult.getSeqNo());
            }
            indexResult.setTook(System.nanoTime() - index.startTime());
            indexResult.freeze();
            return indexResult;
        }
    } catch (RuntimeException | IOException e) {
        try {
            if (e instanceof AlreadyClosedException == false && treatDocumentFailureAsTragicError(index)) {
                failEngine("index id[" + index.id() + "] origin[" + index.origin() + "] seq#[" + index.seqNo() + "]", e);
            } else {
                maybeFailEngine("index id[" + index.id() + "] origin[" + index.origin() + "] seq#[" + index.seqNo() + "]", e);
            }
        } catch (Exception inner) {
            e.addSuppressed(inner);
        }
        throw e;
    }
}
Also used : IOException(java.io.IOException) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) ReleasableLock(org.elasticsearch.common.util.concurrent.ReleasableLock) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) LockObtainFailedException(org.apache.lucene.store.LockObtainFailedException) TranslogCorruptedException(org.elasticsearch.index.translog.TranslogCorruptedException) IOException(java.io.IOException) Translog(org.elasticsearch.index.translog.Translog) Releasable(org.elasticsearch.common.lease.Releasable)

Aggregations

ReleasableLock (org.elasticsearch.common.util.concurrent.ReleasableLock)48 IOException (java.io.IOException)30 AlreadyClosedException (org.apache.lucene.store.AlreadyClosedException)21 LockObtainFailedException (org.apache.lucene.store.LockObtainFailedException)12 TranslogCorruptedException (org.elasticsearch.index.translog.TranslogCorruptedException)12 ArrayList (java.util.ArrayList)7 EOFException (java.io.EOFException)6 Path (java.nio.file.Path)6 Translog (org.elasticsearch.index.translog.Translog)6 IndexFormatTooOldException (org.apache.lucene.index.IndexFormatTooOldException)5 Releasable (org.elasticsearch.common.lease.Releasable)5 Closeable (java.io.Closeable)4 ReadWriteLock (java.util.concurrent.locks.ReadWriteLock)3 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)3 LongSupplier (java.util.function.LongSupplier)3 ParameterizedMessage (org.apache.logging.log4j.message.ParameterizedMessage)3 ReleasableBytesReference (org.elasticsearch.common.bytes.ReleasableBytesReference)3 ReleasableBytesStreamOutput (org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput)3 FileChannel (java.nio.channels.FileChannel)2 Files (java.nio.file.Files)2