Search in sources :

Example 11 with Transaction

use of org.rocksdb.Transaction in project pulsar by apache.

the class RocksdbMetadataStore method storeDelete.

@Override
protected CompletableFuture<Void> storeDelete(String path, Optional<Long> expectedVersion) {
    if (log.isDebugEnabled()) {
        log.debug("storeDelete.path={},instanceId={}", path, instanceId);
    }
    try {
        dbStateLock.readLock().lock();
        if (state == State.CLOSED) {
            throw new MetadataStoreException.AlreadyClosedException("");
        }
        try (Transaction transaction = db.beginTransaction(optionSync)) {
            byte[] pathBytes = toBytes(path);
            byte[] oldValueData = transaction.getForUpdate(optionDontCache, pathBytes, false);
            MetaValue metaValue = MetaValue.parse(oldValueData);
            if (metaValue == null) {
                throw new MetadataStoreException.NotFoundException(String.format("path %s not found.", path));
            }
            if (expectedVersion.isPresent() && !expectedVersion.get().equals(metaValue.getVersion())) {
                throw new MetadataStoreException.BadVersionException(String.format("Version mismatch, actual=%s, expect=%s", metaValue.getVersion(), expectedVersion.get()));
            }
            transaction.delete(pathBytes);
            transaction.commit();
            receivedNotification(new Notification(NotificationType.Deleted, path));
            notifyParentChildrenChanged(path);
            return CompletableFuture.completedFuture(null);
        }
    } catch (Throwable e) {
        return FutureUtil.failedFuture(MetadataStoreException.wrap(e));
    } finally {
        dbStateLock.readLock().unlock();
    }
}
Also used : Transaction(org.rocksdb.Transaction) Notification(org.apache.pulsar.metadata.api.Notification)

Example 12 with Transaction

use of org.rocksdb.Transaction in project FarPlaneTwo by PorkStudios.

the class RocksStorage method markAllDirty.

@Override
@SneakyThrows(RocksDBException.class)
public Stream<POS> markAllDirty(@NonNull Stream<POS> positionsIn, long dirtyTimestamp) {
    // we'll buffer all the positions, lock all of them at once, compare each one and then commit as many as needed. the logic here is identical to
    // RocksTileHandle#markDirty(long), but in bulk, and since RocksTileHandle doesn't cache anything internally, we don't need to get any instances
    // of RocksTileHandle or do any additional synchronization.
    List<POS> positions = positionsIn.distinct().collect(Collectors.toList());
    int length = positions.size();
    if (length == 0) {
        // nothing to do!
        return Stream.empty();
    }
    try (Transaction txn = this.db.beginTransaction(WRITE_OPTIONS)) {
        // convert positions to key bytes
        byte[][] allKeyBytes = positions.stream().map(POS::toBytes).toArray(byte[][]::new);
        byte[][] get;
        {
            // double up the keys and column families to pass them to multiGetForUpdate
            int doubleLength = multiplyExact(length, 2);
            ColumnFamilyHandle[] handles = new ColumnFamilyHandle[doubleLength];
            byte[][] keys = new byte[doubleLength][];
            for (int i = 0; i < doubleLength; ) {
                byte[] keyBytes = allKeyBytes[i >> 1];
                handles[i] = this.cfTileTimestamp;
                keys[i++] = keyBytes;
                handles[i] = this.cfTileDirtyTimestamp;
                keys[i++] = keyBytes;
            }
            // obtain an exclusive lock on both timestamp keys to ensure coherency
            final int MAX_BATCH_SIZE = 65536;
            if (keys.length <= MAX_BATCH_SIZE) {
                get = txn.multiGetForUpdate(READ_OPTIONS, Arrays.asList(handles), keys);
            } else {
                // workaround for https://github.com/facebook/rocksdb/issues/9006
                get = new byte[keys.length][];
                for (int i = 0; i < keys.length; ) {
                    int batchSize = min(keys.length - i, MAX_BATCH_SIZE);
                    byte[][] tmp = txn.multiGetForUpdate(READ_OPTIONS, Arrays.asList(handles).subList(i, i + batchSize), Arrays.copyOfRange(keys, i, i + batchSize));
                    System.arraycopy(tmp, 0, get, i, batchSize);
                    i += batchSize;
                }
            }
        }
        // iterate through positions, updating the dirty timestamps as needed
        List<POS> out = new ArrayList<>(length);
        byte[] dirtyTimestampArray = new byte[Long.BYTES];
        for (int i = 0; i < length; i++) {
            byte[] timestampBytes = get[(i << 1) + 0];
            long timestamp = timestampBytes != null ? // timestamp for this tile exists, extract it from the byte array
            readLongLE(timestampBytes) : TIMESTAMP_BLANK;
            byte[] dirtyTimestampBytes = get[(i << 1) + 1];
            long existingDirtyTimestamp = dirtyTimestampBytes != null ? // dirty timestamp for this tile exists, extract it from the byte array
            readLongLE(dirtyTimestampBytes) : TIMESTAMP_BLANK;
            if (// the tile doesn't exist, so we can't mark it as dirty
            timestamp == TIMESTAMP_BLANK || dirtyTimestamp <= timestamp || dirtyTimestamp <= existingDirtyTimestamp) {
                // skip this position
                continue;
            }
            // store new dirty timestamp in db
            writeLongLE(dirtyTimestampArray, 0, dirtyTimestamp);
            txn.put(this.cfTileDirtyTimestamp, allKeyBytes[i], dirtyTimestampArray);
            // save the position to return it as part of the result stream
            out.add(positions.get(i));
        }
        if (!out.isEmpty()) {
            // non-empty list indicates that at least some positions were modified, so we should commit the transaction
            txn.commit();
            this.listeners.forEach(listener -> listener.tilesDirty(out.stream()));
            return out.stream();
        } else {
            // no positions were modified...
            return Stream.empty();
        }
    }
}
Also used : Transaction(org.rocksdb.Transaction) ArrayList(java.util.ArrayList) SneakyThrows(lombok.SneakyThrows)

Example 13 with Transaction

use of org.rocksdb.Transaction in project FarPlaneTwo by PorkStudios.

the class RocksTileHandle method clearDirty.

@Override
@SneakyThrows(RocksDBException.class)
public boolean clearDirty() {
    try (Transaction txn = this.storage.db.beginTransaction(WRITE_OPTIONS)) {
        byte[] keyBytes = this.pos.toBytes();
        if (txn.getForUpdate(READ_OPTIONS, this.storage.cfTileDirtyTimestamp, keyBytes, true) == null) {
            // exit without committing the transaction
            return false;
        }
        // store new dirty timestamp in db
        txn.delete(this.storage.cfTileDirtyTimestamp, keyBytes);
        // commit transaction and report that a change was made
        txn.commit();
        return true;
    }
}
Also used : Transaction(org.rocksdb.Transaction) SneakyThrows(lombok.SneakyThrows)

Aggregations

Transaction (org.rocksdb.Transaction)13 Notification (org.apache.pulsar.metadata.api.Notification)6 SneakyThrows (lombok.SneakyThrows)4 Stat (org.apache.pulsar.metadata.api.Stat)3 ByteBuf (io.netty.buffer.ByteBuf)1 ArrayList (java.util.ArrayList)1