use of lombok.Data in project pravega by pravega.
the class UtilsWrapper method getExtendedChunkInfoList.
/**
* Returns the list of {@link ExtendedChunkInfo} which contain data about all chunks for the segment.
*
* @param streamSegmentName Name of the segment.
* @param checkStorage Whether to retrieve information from underlying {@link ChunkStorage}.
* @return A CompletableFuture that, when completed, will contain a list of {@link ExtendedChunkInfo} objects associated with the segment.
* If the operation failed, it will be completed with the appropriate exception.
*/
public CompletableFuture<List<ExtendedChunkInfo>> getExtendedChunkInfoList(String streamSegmentName, boolean checkStorage) {
Preconditions.checkNotNull(streamSegmentName, "streamSegmentName");
val infoList = Collections.synchronizedList(new ArrayList<ExtendedChunkInfo>());
return chunkedSegmentStorage.executeSerialized(() -> chunkedSegmentStorage.tryWith(chunkedSegmentStorage.getMetadataStore().beginTransaction(true, streamSegmentName), txn -> txn.get(streamSegmentName).thenComposeAsync(storageMetadata -> {
val segmentMetadata = (SegmentMetadata) storageMetadata;
segmentMetadata.checkInvariants();
val iterator = new ChunkIterator(chunkedSegmentStorage.getExecutor(), txn, segmentMetadata);
val startOffset = new AtomicLong(segmentMetadata.getFirstChunkStartOffset());
iterator.forEach((metadata, name) -> {
infoList.add(ExtendedChunkInfo.builder().chunkName(name).startOffset(startOffset.get()).lengthInMetadata(metadata.getLength()).build());
startOffset.addAndGet(metadata.getLength());
});
return completedFuture(infoList);
}, chunkedSegmentStorage.getExecutor()).thenComposeAsync(v -> {
val futures = new ArrayList<CompletableFuture<Void>>();
if (checkStorage) {
for (val info : infoList) {
futures.add(chunkedSegmentStorage.getChunkStorage().exists(info.getChunkName()).thenComposeAsync(doesExist -> {
if (doesExist) {
return chunkedSegmentStorage.getChunkStorage().getInfo(info.getChunkName()).thenAcceptAsync(chunkInfo -> {
info.setLengthInStorage(chunkInfo.getLength());
info.setExistsInStorage(true);
}, chunkedSegmentStorage.getExecutor());
} else {
return completedFuture(null);
}
}, chunkedSegmentStorage.getExecutor()));
}
}
return Futures.allOf(futures);
}, chunkedSegmentStorage.getExecutor()).thenApplyAsync(vv -> infoList, chunkedSegmentStorage.getExecutor()), chunkedSegmentStorage.getExecutor()), streamSegmentName);
}
use of lombok.Data in project pravega by pravega.
the class BaseMetadataStore method performCommit.
/**
* Performs commit.
*/
private CompletableFuture<Void> performCommit(MetadataTransaction txn, boolean lazyWrite, Map<String, TransactionData> txnData, ArrayList<String> modifiedKeys, ArrayList<TransactionData> modifiedValues) {
return CompletableFuture.runAsync(() -> {
// Step 2 : Check whether transaction is safe to commit.
validateCommit(txn, txnData, modifiedKeys, modifiedValues);
}, executor).thenComposeAsync(v -> {
// This operation may call external storage.
return writeToMetadataStore(lazyWrite, modifiedValues);
}, executor).thenComposeAsync(v -> executeExternalCommitAction(txn), executor).thenRunAsync(() -> {
// If we reach here then it means transaction is safe to commit.
// Step 4: Update buffer.
val committedVersion = version.incrementAndGet();
val toAdd = new HashMap<String, TransactionData>();
int delta = 0;
for (String key : modifiedKeys) {
TransactionData data = getDeepCopy(txnData.get(key));
data.setVersion(committedVersion);
toAdd.put(key, data);
if (data.isCreated()) {
delta++;
}
if (data.isDeleted()) {
delta--;
}
}
bufferedTxnData.putAll(toAdd);
bufferCount.addAndGet(delta);
}, executor);
}
use of lombok.Data in project pravega by pravega.
the class BaseMetadataStore method get.
/**
* Retrieves the metadata for given key.
*
* @param txn Transaction.
* @param key key to use to retrieve metadata.
* @return A CompletableFuture that, when completed, will contain metadata for given key. Null if key was not found.
* @throws CompletionException If the operation failed, it will be completed with the appropriate exception. Notable Exceptions:
* {@link StorageMetadataException} Exception related to storage metadata operations.
*/
@Override
public CompletableFuture<StorageMetadata> get(MetadataTransaction txn, String key) {
Preconditions.checkArgument(null != txn, "txn must not be null");
if (null == key) {
return CompletableFuture.completedFuture(null);
}
val t = new Timer();
val txnData = txn.getData();
// Record is found in transaction data itself.
TransactionData data = txnData.get(key);
if (null != data) {
GET_LATENCY.reportSuccessEvent(t.getElapsed());
METADATA_FOUND_IN_TXN.inc();
return CompletableFuture.completedFuture(data.getValue());
}
// Prevent the key from getting evicted.
addToActiveKeySet(key);
return CompletableFuture.supplyAsync(() -> bufferedTxnData.get(key), executor).thenApplyAsync(dataFromBuffer -> {
if (dataFromBuffer != null) {
METADATA_FOUND_IN_BUFFER.inc();
// Make sure it is a deep copy.
return copyToTransaction(txn, key, dataFromBuffer);
}
return null;
}, executor).thenComposeAsync(retValue -> {
if (retValue != null) {
return CompletableFuture.completedFuture(retValue);
}
// Try to find it in store.
return loadFromStore(key).thenApplyAsync(dataFromStore -> copyToTransaction(txn, key, dataFromStore), executor);
}, executor).whenCompleteAsync((v, ex) -> {
removeFromActiveKeySet(key);
GET_LATENCY.reportSuccessEvent(t.getElapsed());
}, executor);
}
use of lombok.Data in project pravega by pravega.
the class SystemJournal method createSystemSnapshotRecord.
private CompletableFuture<SystemSnapshotRecord> createSystemSnapshotRecord(MetadataTransaction txn, boolean validateSegment, boolean validateChunks) {
val systemSnapshot = SystemSnapshotRecord.builder().epoch(epoch).fileIndex(currentFileIndex.get()).segmentSnapshotRecords(new ArrayList<>()).build();
val futures = Collections.synchronizedList(new ArrayList<CompletableFuture<Void>>());
for (val systemSegment : systemSegments) {
// Find segment metadata.
val future = txn.get(systemSegment).thenComposeAsync(metadata -> {
val segmentMetadata = (SegmentMetadata) metadata;
segmentMetadata.checkInvariants();
val segmentSnapshot = SegmentSnapshotRecord.builder().segmentMetadata(segmentMetadata).chunkMetadataCollection(new ArrayList<>()).build();
// Enumerate all chunks.
val currentChunkName = new AtomicReference<>(segmentMetadata.getFirstChunk());
val dataSize = new AtomicLong();
val chunkCount = new AtomicLong();
// For each chunk
return Futures.loop(() -> null != currentChunkName.get(), () -> txn.get(currentChunkName.get()).thenComposeAsync(m -> {
val currentChunkMetadata = (ChunkMetadata) m;
CompletableFuture<Void> f;
Preconditions.checkState(null != currentChunkMetadata, "currentChunkMetadata must not be null");
if (validateChunks) {
f = chunkStorage.getInfo(currentChunkName.get()).thenAcceptAsync(chunkInfo -> Preconditions.checkState(chunkInfo.getLength() >= currentChunkMetadata.getLength(), "Wrong chunk length chunkInfo=%d, currentMetadata=%d.", chunkInfo.getLength(), currentChunkMetadata.getLength()), executor);
} else {
f = CompletableFuture.completedFuture(null);
}
return f.thenAcceptAsync(v -> {
chunkCount.getAndIncrement();
dataSize.addAndGet(currentChunkMetadata.getLength());
segmentSnapshot.chunkMetadataCollection.add(currentChunkMetadata);
// move to next chunk
currentChunkName.set(currentChunkMetadata.getNextChunk());
}, executor);
}, executor), executor).thenAcceptAsync(v -> {
// Validate
if (validateSegment) {
Preconditions.checkState(chunkCount.get() == segmentMetadata.getChunkCount(), "Wrong chunk count. Segment=%s", segmentMetadata);
Preconditions.checkState(dataSize.get() == segmentMetadata.getLength() - segmentMetadata.getFirstChunkStartOffset(), "Data size does not match dataSize (%s). Segment=%s", dataSize.get(), segmentMetadata);
}
// Add to the system snapshot.
synchronized (systemSnapshot) {
systemSnapshot.segmentSnapshotRecords.add(segmentSnapshot);
}
}, executor);
}, executor);
futures.add(future);
}
return Futures.allOf(futures).thenApplyAsync(vv -> {
systemSnapshot.checkInvariants();
return systemSnapshot;
}, executor);
}
use of lombok.Data in project pravega by pravega.
the class SystemJournal method bootstrap.
/**
* Bootstrap the metadata about storage metadata segments by reading and processing the journal.
*
* @param epoch Epoch of the current container instance.
* @param snapshotInfoStore {@link SnapshotInfoStore} that stores {@link SnapshotInfo}.
*/
public CompletableFuture<Void> bootstrap(long epoch, SnapshotInfoStore snapshotInfoStore) {
this.epoch = epoch;
this.snapshotInfoStore = Preconditions.checkNotNull(snapshotInfoStore, "snapshotInfoStore");
Preconditions.checkState(!reentryGuard.getAndSet(true), "bootstrap called multiple times.");
log.debug("SystemJournal[{}] BOOT started.", containerId);
Timer t = new Timer();
// Start a transaction
val txn = metadataStore.beginTransaction(false, getSystemSegments());
val state = new BootstrapState();
// Step 1: Create metadata records for system segments from latest snapshot.
return findLatestSnapshot().thenComposeAsync(snapshot -> applySystemSnapshotRecord(txn, state, snapshot), executor).thenComposeAsync(latestSnapshot -> {
// Step 2: For each epoch, find the corresponding system journal files, process them and apply operations recorded.
return applySystemLogOperations(txn, state, latestSnapshot);
}, executor).thenComposeAsync(v -> {
// Step 3: Adjust the length of the last chunk.
if (config.isLazyCommitEnabled()) {
return adjustLastChunkLengths(txn);
} else {
return CompletableFuture.completedFuture(null);
}
}, executor).thenComposeAsync(v -> {
// Step 4: Apply the truncate offsets.
return applyFinalTruncateOffsets(txn, state);
}, executor).thenComposeAsync(v -> {
// Step 5: Check invariants. These should never fail.
if (config.isSelfCheckEnabled()) {
Preconditions.checkState(currentFileIndex.get() == 0, "currentFileIndex must be zero");
Preconditions.checkState(systemJournalOffset.get() == 0, "systemJournalOffset must be zero");
Preconditions.checkState(newChunkRequired.get(), "newChunkRequired must be true");
}
// Step 6: Create a snapshot record and validate it. Save it in journals.
return createSystemSnapshotRecord(txn, true, config.isSelfCheckEnabled()).thenComposeAsync(systemSnapshotRecord -> writeRecordBatch(Collections.singletonList(systemSnapshotRecord)), executor).thenRunAsync(() -> newChunkRequired.set(true), executor);
}, executor).thenComposeAsync(v -> {
// Step 7: Finally commit all data.
return txn.commit(true, true);
}, executor).whenCompleteAsync((v, e) -> {
txn.close();
log.info("SystemJournal[{}] BOOT complete - applied {} records in {} journals. Total time = {} ms.", containerId, state.recordsProcessedCount.get(), state.filesProcessedCount.get(), t.getElapsedMillis());
}, executor);
}
Aggregations