All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artipie.asto.s3.EstimatedContentCompliment Maven / Gradle / Ivy

There is a newer version: v1.17.16
Show newest version
/*
 * The MIT License (MIT) Copyright (c) 2020-2023 artipie.com
 * https://github.com/artipie/asto/LICENSE.txt
 */
package com.artipie.asto.s3;

import com.artipie.asto.ArtipieIOException;
import com.artipie.asto.Content;
import hu.akarnokd.rxjava2.interop.SingleInterop;
import io.reactivex.Flowable;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import org.cqfn.rio.file.File;

/**
 * Complements {@link Content} with size if size is unknown.
 * 

* Size calculated by reading up to `limit` content bytes. * If end of content has not been reached by reading `limit` of bytes * then original content is returned. * * @since 0.1 */ final class EstimatedContentCompliment { /** * The original content. */ private final Content original; /** * The limit. */ private final long limit; /** * Ctor. * * @param original Original content. * @param limit Content reading limit. */ EstimatedContentCompliment(final Content original, final long limit) { this.original = original; this.limit = limit; } /** * Ctor. * * @param original Original content. */ EstimatedContentCompliment(final Content original) { this(original, Long.MAX_VALUE); } /** * Initialize future of Content. * * @return The future. */ public CompletionStage estimate() { final CompletableFuture res; if (this.original.size().isPresent()) { res = CompletableFuture.completedFuture(this.original); } else { res = this.readUntilLimit(); } return res; } /** * Read until limit. * * @return The future. */ private CompletableFuture readUntilLimit() { final Path temp; try { temp = Files.createTempFile( S3Storage.class.getSimpleName(), ".upload.tmp" ); } catch (final IOException ex) { throw new ArtipieIOException(ex); } final Flowable data = Flowable.fromPublisher( new File(temp).content() ).doOnError(error -> Files.deleteIfExists(temp)); return new File(temp) .write(this.original) .thenCompose( nothing -> data .map(Buffer::remaining) .scanWith(() -> 0L, Long::sum) .takeUntil(total -> total >= this.limit) .lastOrError() .to(SingleInterop.get()) .toCompletableFuture() ) .thenApply( last -> { final Optional size; if (last >= this.limit) { size = Optional.empty(); } else { size = Optional.of(last); } return new Content.From( size, data.doAfterTerminate( () -> Files.deleteIfExists(temp) ) ); } ).toCompletableFuture(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy