Search in sources :

Example 1 with Timer

use of org.janusgraph.diskstorage.util.time.Timer in project janusgraph by JanusGraph.

the class ConsistentKeyLocker method tryWriteLockOnce.

private WriteResult tryWriteLockOnce(StaticBuffer key, StaticBuffer del, StoreTransaction txh) {
    Throwable t = null;
    final Timer writeTimer = times.getTimer().start();
    StaticBuffer newLockCol = serializer.toLockCol(writeTimer.getStartTime(), rid, times);
    Entry newLockEntry = StaticArrayEntry.of(newLockCol, zeroBuf);
    StoreTransaction newTx = null;
    try {
        newTx = overrideTimestamp(txh, writeTimer.getStartTime());
        store.mutate(key, Collections.singletonList(newLockEntry), null == del ? KeyColumnValueStore.NO_DELETIONS : Collections.singletonList(del), newTx);
        newTx.commit();
        newTx = null;
    } catch (BackendException e) {
        log.debug("Lock write attempt failed with exception", e);
        t = e;
    } finally {
        rollbackIfNotNull(newTx);
    }
    writeTimer.stop();
    return new WriteResult(writeTimer.elapsed(), writeTimer.getStartTime(), newLockCol, t);
}
Also used : StaticArrayEntry(org.janusgraph.diskstorage.util.StaticArrayEntry) Entry(org.janusgraph.diskstorage.Entry) Timer(org.janusgraph.diskstorage.util.time.Timer) StoreTransaction(org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) BackendException(org.janusgraph.diskstorage.BackendException) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException)

Example 2 with Timer

use of org.janusgraph.diskstorage.util.time.Timer in project janusgraph by JanusGraph.

the class ConsistentKeyLocker method tryDeleteLockOnce.

private WriteResult tryDeleteLockOnce(StaticBuffer key, StaticBuffer col, StoreTransaction txh) {
    Throwable t = null;
    final Timer delTimer = times.getTimer().start();
    StoreTransaction newTx = null;
    try {
        newTx = overrideTimestamp(txh, delTimer.getStartTime());
        store.mutate(key, Collections.emptyList(), Collections.singletonList(col), newTx);
        newTx.commit();
        newTx = null;
    } catch (BackendException e) {
        t = e;
    } finally {
        rollbackIfNotNull(newTx);
    }
    delTimer.stop();
    return new WriteResult(delTimer.elapsed(), delTimer.getStartTime(), null, t);
}
Also used : Timer(org.janusgraph.diskstorage.util.time.Timer) StoreTransaction(org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) BackendException(org.janusgraph.diskstorage.BackendException) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException)

Example 3 with Timer

use of org.janusgraph.diskstorage.util.time.Timer in project janusgraph by JanusGraph.

the class GraphIndexStatusWatcher method call.

@Override
public GraphIndexStatusReport call() throws InterruptedException {
    Preconditions.checkNotNull(g, "Graph instance must not be null");
    Preconditions.checkNotNull(graphIndexName, "Index name must not be null");
    Preconditions.checkNotNull(statuses, "Target statuses must not be null");
    Preconditions.checkArgument(statuses.size() > 0, "Target statuses must include at least one status");
    Map<String, SchemaStatus> notConverged = new HashMap<>();
    Map<String, SchemaStatus> converged = new HashMap<>();
    JanusGraphIndex idx;
    Timer t = new Timer(TimestampProviders.MILLI).start();
    boolean timedOut;
    while (true) {
        JanusGraphManagement management = null;
        try {
            management = g.openManagement();
            idx = management.getGraphIndex(graphIndexName);
            for (PropertyKey pk : idx.getFieldKeys()) {
                SchemaStatus s = idx.getIndexStatus(pk);
                LOGGER.debug("Key {} has status {}", pk, s);
                if (!statuses.contains(s))
                    notConverged.put(pk.toString(), s);
                else
                    converged.put(pk.toString(), s);
            }
        } finally {
            if (null != management)
                // Let an exception here propagate up the stack
                management.rollback();
        }
        if (!notConverged.isEmpty()) {
            String waitingOn = StringUtils.join(notConverged, "=", ",");
            LOGGER.info("Some key(s) on index {} do not currently have status(es) {}: {}", graphIndexName, statuses, waitingOn);
        } else {
            LOGGER.info("All {} key(s) on index {} have status(es) {}", converged.size(), graphIndexName, statuses);
            return new GraphIndexStatusReport(true, graphIndexName, statuses, notConverged, converged, t.elapsed());
        }
        timedOut = null != timeout && 0 < t.elapsed().compareTo(timeout);
        if (timedOut) {
            LOGGER.info("Timed out ({}) while waiting for index {} to converge on status(es) {}", timeout, graphIndexName, statuses);
            return new GraphIndexStatusReport(false, graphIndexName, statuses, notConverged, converged, t.elapsed());
        }
        notConverged.clear();
        converged.clear();
        Thread.sleep(poll.toMillis());
    }
}
Also used : JanusGraphManagement(org.janusgraph.core.schema.JanusGraphManagement) Timer(org.janusgraph.diskstorage.util.time.Timer) HashMap(java.util.HashMap) JanusGraphIndex(org.janusgraph.core.schema.JanusGraphIndex) SchemaStatus(org.janusgraph.core.schema.SchemaStatus) PropertyKey(org.janusgraph.core.PropertyKey)

Example 4 with Timer

use of org.janusgraph.diskstorage.util.time.Timer in project janusgraph by JanusGraph.

the class RelationIndexStatusWatcher method call.

/**
 * Poll a relation index until it has a certain {@link SchemaStatus},
 * or until a configurable timeout is exceeded.
 *
 * @return a report with information about schema state, execution duration, and the index
 */
@Override
public RelationIndexStatusReport call() throws InterruptedException {
    Preconditions.checkNotNull(g, "Graph instance must not be null");
    Preconditions.checkNotNull(relationIndexName, "Index name must not be null");
    Preconditions.checkNotNull(statuses, "Target statuses must not be null");
    Preconditions.checkArgument(statuses.size() > 0, "Target statuses must include at least one status");
    RelationTypeIndex idx;
    Timer t = new Timer(TimestampProviders.MILLI).start();
    boolean timedOut;
    while (true) {
        final SchemaStatus actualStatus;
        JanusGraphManagement management = null;
        try {
            management = g.openManagement();
            idx = management.getRelationIndex(management.getRelationType(relationTypeName), relationIndexName);
            actualStatus = idx.getIndexStatus();
            LOGGER.info("Index {} (relation type {}) has status {}", relationIndexName, relationTypeName, actualStatus);
            if (statuses.contains(actualStatus)) {
                return new RelationIndexStatusReport(true, relationIndexName, relationTypeName, actualStatus, statuses, t.elapsed());
            }
        } finally {
            if (null != management)
                // Let an exception here propagate up the stack
                management.rollback();
        }
        timedOut = null != timeout && 0 < t.elapsed().compareTo(timeout);
        if (timedOut) {
            LOGGER.info("Timed out ({}) while waiting for index {} (relation type {}) to reach status(es) {}", timeout, relationIndexName, relationTypeName, statuses);
            return new RelationIndexStatusReport(false, relationIndexName, relationTypeName, actualStatus, statuses, t.elapsed());
        }
        Thread.sleep(poll.toMillis());
    }
}
Also used : JanusGraphManagement(org.janusgraph.core.schema.JanusGraphManagement) Timer(org.janusgraph.diskstorage.util.time.Timer) RelationTypeIndex(org.janusgraph.core.schema.RelationTypeIndex) SchemaStatus(org.janusgraph.core.schema.SchemaStatus)

Example 5 with Timer

use of org.janusgraph.diskstorage.util.time.Timer in project janusgraph by JanusGraph.

the class ConsistentKeyIDAuthority method getIDBlock.

@Override
public synchronized IDBlock getIDBlock(final int partition, final int idNamespace, Duration timeout) throws BackendException {
    Preconditions.checkArgument(partition >= 0 && partition < (1 << partitionBitWidth), "Invalid partition id [%s] for bit width [%s]", partition, partitionBitWidth);
    // can be any non-negative value
    Preconditions.checkArgument(idNamespace >= 0);
    final Timer methodTime = times.getTimer().start();
    final long blockSize = getBlockSize(idNamespace);
    final long idUpperBound = getIdUpperBound(idNamespace);
    final int maxAvailableBits = (VariableLong.unsignedBitLength(idUpperBound) - 1) - uniqueIdBitWidth;
    Preconditions.checkArgument(maxAvailableBits > 0, "Unique id bit width [%s] is too wide for id-namespace [%s] id bound [%s]", uniqueIdBitWidth, idNamespace, idUpperBound);
    final long idBlockUpperBound = (1L << maxAvailableBits);
    final List<Integer> exhaustedUniquePIDs = new ArrayList<>(randomUniqueIDLimit);
    Duration backoffMS = idApplicationWaitMS;
    Preconditions.checkArgument(idBlockUpperBound > blockSize, "Block size [%s] is larger than upper bound [%s] for bit width [%s]", blockSize, idBlockUpperBound, uniqueIdBitWidth);
    while (methodTime.elapsed().compareTo(timeout) < 0) {
        final int uniquePID = getUniquePartitionID();
        final StaticBuffer partitionKey = getPartitionKey(partition, idNamespace, uniquePID);
        try {
            long nextStart = getCurrentID(partitionKey);
            if (idBlockUpperBound - blockSize <= nextStart) {
                log.info("ID overflow detected on partition({})-namespace({}) with uniqueid {}. Current id {}, block size {}, and upper bound {} for bit width {}.", partition, idNamespace, uniquePID, nextStart, blockSize, idBlockUpperBound, uniqueIdBitWidth);
                if (randomizeUniqueId) {
                    exhaustedUniquePIDs.add(uniquePID);
                    if (exhaustedUniquePIDs.size() == randomUniqueIDLimit)
                        throw new IDPoolExhaustedException(String.format("Exhausted %d uniqueid(s) on partition(%d)-namespace(%d): %s", exhaustedUniquePIDs.size(), partition, idNamespace, StringUtils.join(exhaustedUniquePIDs, ",")));
                    else
                        throw new UniqueIDExhaustedException(String.format("Exhausted ID partition(%d)-namespace(%d) with uniqueid %d (uniqueid attempt %d/%d)", partition, idNamespace, uniquePID, exhaustedUniquePIDs.size(), randomUniqueIDLimit));
                }
                throw new IDPoolExhaustedException("Exhausted id block for partition(" + partition + ")-namespace(" + idNamespace + ") with upper bound: " + idBlockUpperBound);
            }
            // calculate the start (inclusive) and end (exclusive) of the allocation we're about to attempt
            assert idBlockUpperBound - blockSize > nextStart;
            long nextEnd = nextStart + blockSize;
            StaticBuffer target = null;
            // attempt to write our claim on the next id block
            boolean success = false;
            try {
                Timer writeTimer = times.getTimer().start();
                target = getBlockApplication(nextEnd, writeTimer.getStartTime());
                // copy for the inner class
                final StaticBuffer finalTarget = target;
                BackendOperation.execute(txh -> {
                    idStore.mutate(partitionKey, Collections.singletonList(StaticArrayEntry.of(finalTarget)), KeyColumnValueStore.NO_DELETIONS, txh);
                    return true;
                }, this, times);
                writeTimer.stop();
                final boolean distributed = manager.getFeatures().isDistributed();
                Duration writeElapsed = writeTimer.elapsed();
                if (idApplicationWaitMS.compareTo(writeElapsed) < 0 && distributed) {
                    throw new TemporaryBackendException("Wrote claim for id block [" + nextStart + ", " + nextEnd + ") in " + (writeElapsed) + " => too slow, threshold is: " + idApplicationWaitMS);
                } else {
                    assert 0 != target.length();
                    final StaticBuffer[] slice = getBlockSlice(nextEnd);
                    if (distributed) {
                        sleepAndConvertInterrupts(idApplicationWaitMS.plus(waitGracePeriod));
                    }
                    // Read all id allocation claims on this partition, for the counter value we're claiming
                    final List<Entry> blocks = BackendOperation.execute((BackendOperation.Transactional<List<Entry>>) txh -> idStore.getSlice(new KeySliceQuery(partitionKey, slice[0], slice[1]), txh), this, times);
                    if (blocks == null)
                        throw new TemporaryBackendException("Could not read from storage");
                    if (blocks.isEmpty())
                        throw new PermanentBackendException("It seems there is a race-condition in the block application. " + "If you have multiple JanusGraph instances running on one physical machine, ensure that they have unique machine idAuthorities");
                    /* If our claim is the lexicographically first one, then our claim
                         * is the most senior one and we own this id block
                         */
                    if (target.equals(blocks.get(0).getColumnAs(StaticBuffer.STATIC_FACTORY))) {
                        ConsistentKeyIDBlock idBlock = new ConsistentKeyIDBlock(nextStart, blockSize, uniqueIdBitWidth, uniquePID);
                        if (log.isDebugEnabled()) {
                            log.debug("Acquired ID block [{}] on partition({})-namespace({}) (my rid is {})", idBlock, partition, idNamespace, uid);
                        }
                        success = true;
                        return idBlock;
                    } else {
                        // Another claimant beat us to this id block -- try again.
                        log.debug("Failed to acquire ID block [{},{}) (another host claimed it first)", nextStart, nextEnd);
                    }
                }
            } finally {
                if (!success && null != target) {
                    // Delete claim to not pollute id space
                    for (int attempt = 0; attempt < ROLLBACK_ATTEMPTS; attempt++) {
                        try {
                            // copy for the inner class
                            final StaticBuffer finalTarget = target;
                            BackendOperation.execute(txh -> {
                                idStore.mutate(partitionKey, KeyColumnValueStore.NO_ADDITIONS, Collections.singletonList(finalTarget), txh);
                                return true;
                            }, new // Use normal consistency level for these non-critical delete operations
                            BackendOperation.TransactionalProvider() {

                                @Override
                                public StoreTransaction openTx() throws BackendException {
                                    return manager.beginTransaction(storeTxConfigBuilder.build());
                                }

                                @Override
                                public void close() {
                                }
                            }, times);
                            break;
                        } catch (BackendException e) {
                            log.warn("Storage exception while deleting old block application - retrying in {}", rollbackWaitTime, e);
                            if (!rollbackWaitTime.isZero())
                                sleepAndConvertInterrupts(rollbackWaitTime);
                        }
                    }
                }
            }
        } catch (UniqueIDExhaustedException e) {
            // No need to increment the backoff wait time or to sleep
            log.warn(e.getMessage());
        } catch (TemporaryBackendException e) {
            backoffMS = Durations.min(backoffMS.multipliedBy(2), idApplicationWaitMS.multipliedBy(32));
            log.warn("Temporary storage exception while acquiring id block - retrying in {}: {}", backoffMS, e);
            sleepAndConvertInterrupts(backoffMS);
        }
    }
    throw new TemporaryLockingException(String.format("Reached timeout %d (%s elapsed) when attempting to allocate id block on partition(%d)-namespace(%d)", timeout.getNano(), methodTime, partition, idNamespace));
}
Also used : KeyRange(org.janusgraph.diskstorage.keycolumnvalue.KeyRange) StandardBaseTransactionConfig(org.janusgraph.diskstorage.util.StandardBaseTransactionConfig) CLUSTER_MAX_PARTITIONS(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.CLUSTER_MAX_PARTITIONS) IDBlock(org.janusgraph.diskstorage.IDBlock) StoreManager(org.janusgraph.diskstorage.keycolumnvalue.StoreManager) StringUtils(org.janusgraph.util.StringUtils) BackendOperation(org.janusgraph.diskstorage.util.BackendOperation) LoggerFactory(org.slf4j.LoggerFactory) Random(java.util.Random) Timer(org.janusgraph.diskstorage.util.time.Timer) NumberUtil(org.janusgraph.util.stats.NumberUtil) StaticArrayEntry(org.janusgraph.diskstorage.util.StaticArrayEntry) ArrayList(java.util.ArrayList) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) IDAUTHORITY_CAV_TAG(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.IDAUTHORITY_CAV_TAG) IDAUTHORITY_CAV_BITS(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.IDAUTHORITY_CAV_BITS) VariableLong(org.janusgraph.graphdb.database.idhandling.VariableLong) Duration(java.time.Duration) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) StoreTransaction(org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction) IDPoolExhaustedException(org.janusgraph.graphdb.database.idassigner.IDPoolExhaustedException) BackendException(org.janusgraph.diskstorage.BackendException) IDAUTHORITY_CONFLICT_AVOIDANCE(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.IDAUTHORITY_CONFLICT_AVOIDANCE) Logger(org.slf4j.Logger) Configuration(org.janusgraph.diskstorage.configuration.Configuration) WriteByteBuffer(org.janusgraph.diskstorage.util.WriteByteBuffer) TimestampProvider(org.janusgraph.diskstorage.util.time.TimestampProvider) KeySliceQuery(org.janusgraph.diskstorage.keycolumnvalue.KeySliceQuery) Durations(org.janusgraph.diskstorage.util.time.Durations) WriteBufferUtil(org.janusgraph.diskstorage.util.WriteBufferUtil) Instant(java.time.Instant) KeyColumnValueStore(org.janusgraph.diskstorage.keycolumnvalue.KeyColumnValueStore) TIMESTAMP_PROVIDER(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.TIMESTAMP_PROVIDER) List(java.util.List) Entry(org.janusgraph.diskstorage.Entry) BufferUtil(org.janusgraph.diskstorage.util.BufferUtil) Preconditions(com.google.common.base.Preconditions) IDAUTHORITY_CAV_RETRIES(org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.IDAUTHORITY_CAV_RETRIES) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException) Collections(java.util.Collections) TemporaryLockingException(org.janusgraph.diskstorage.locking.TemporaryLockingException) StoreTransaction(org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction) ArrayList(java.util.ArrayList) BackendOperation(org.janusgraph.diskstorage.util.BackendOperation) StaticArrayEntry(org.janusgraph.diskstorage.util.StaticArrayEntry) Entry(org.janusgraph.diskstorage.Entry) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) ArrayList(java.util.ArrayList) List(java.util.List) KeySliceQuery(org.janusgraph.diskstorage.keycolumnvalue.KeySliceQuery) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException) Duration(java.time.Duration) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) BackendException(org.janusgraph.diskstorage.BackendException) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) Timer(org.janusgraph.diskstorage.util.time.Timer) IDPoolExhaustedException(org.janusgraph.graphdb.database.idassigner.IDPoolExhaustedException) TemporaryLockingException(org.janusgraph.diskstorage.locking.TemporaryLockingException)

Aggregations

Timer (org.janusgraph.diskstorage.util.time.Timer)6 BackendException (org.janusgraph.diskstorage.BackendException)3 PermanentBackendException (org.janusgraph.diskstorage.PermanentBackendException)3 TemporaryBackendException (org.janusgraph.diskstorage.TemporaryBackendException)3 StoreTransaction (org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction)3 Duration (java.time.Duration)2 JanusGraphManagement (org.janusgraph.core.schema.JanusGraphManagement)2 SchemaStatus (org.janusgraph.core.schema.SchemaStatus)2 Entry (org.janusgraph.diskstorage.Entry)2 StaticBuffer (org.janusgraph.diskstorage.StaticBuffer)2 StaticArrayEntry (org.janusgraph.diskstorage.util.StaticArrayEntry)2 Preconditions (com.google.common.base.Preconditions)1 Instant (java.time.Instant)1 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Random (java.util.Random)1 PropertyKey (org.janusgraph.core.PropertyKey)1 JanusGraphIndex (org.janusgraph.core.schema.JanusGraphIndex)1