Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 2 additions & 31 deletions oap-storage/oap-storage-cloud-aws-s3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,10 @@
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk.crt</groupId>
<artifactId>aws-crt</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-transfer-manager</artifactId>
<exclusions>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sdk-core</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>utils</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>annotations</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>regions</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk.crt</groupId>
<artifactId>aws-crt</artifactId>
</exclusion>
</exclusions>
<artifactId>apache5-client</artifactId>
<version>2.50.2</version>
</dependency>

<dependency>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

import static dev.khbd.interp4j.core.Interpolations.s;
Expand Down Expand Up @@ -233,49 +232,48 @@ private URI buildUri( CloudURI path ) {
}

@Override
public CompletableFuture<Boolean> blobExistsAsync( CloudURI path ) {
public boolean blobExists( CloudURI path ) {
FTPClient client = borrow();
boolean healthy = false;
try {
boolean exists = findFile( client, absolute( path.path ) ) != null;
healthy = true;
return CompletableFuture.completedFuture( exists );
return exists;
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( client, healthy );
}
}

@Override
public CompletableFuture<Boolean> containerExistsAsync( CloudURI path ) {
public boolean containerExists( CloudURI path ) {
try {
FTPClient client = borrow();
release( client, true );
return CompletableFuture.completedFuture( true );
return true;
} catch( CloudException e ) {
return CompletableFuture.completedFuture( false );
return false;
}
}

@Override
public CompletableFuture<Void> deleteBlobAsync( CloudURI path ) {
public void deleteBlob( CloudURI path ) {
FTPClient client = borrow();
boolean healthy = false;
try {
if( !client.deleteFile( absolute( path.path ) ) ) {
healthy = true;
return CompletableFuture.failedFuture( new CloudException( "cannot delete " + path ) );
throw new CloudException( "cannot delete " + path );
}

if( removeEmptyFolders ) {
removeEmptyParents( client, parentOf( absolute( path.path ) ) );
}

healthy = true;
return CompletableFuture.completedFuture( null );
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( client, healthy );
}
Expand All @@ -296,59 +294,58 @@ private void removeEmptyParents( FTPClient client, String dirPath ) throws IOExc
}

@Override
public CompletableFuture<Void> deleteContainerAsync( CloudURI path ) throws CloudException {
public void deleteContainer( CloudURI path ) throws CloudException {
throw new CloudException( "not supported" );
}

@Override
public CompletableFuture<Boolean> createContainerAsync( CloudURI path ) {
return CompletableFuture.completedFuture( false );
public boolean createContainer( CloudURI path ) {
return false;
}

@Override
public CompletableFuture<Boolean> deleteContainerIfEmptyAsync( CloudURI path ) {
return CompletableFuture.completedFuture( false );
public boolean deleteContainerIfEmpty( CloudURI path ) {
return false;
}

@Override
public CompletableFuture<? extends FileSystem.StorageItem> getMetadataAsync( CloudURI path ) {
public FileSystem.StorageItem getMetadata( CloudURI path ) {
FTPClient client = borrow();
boolean healthy = false;
try {
FTPFile file = findFile( client, absolute( path.path ) );
healthy = true;
if( file == null ) return CompletableFuture.completedFuture( null );
if( file == null ) return null;

return CompletableFuture.completedFuture( toStorageItem( path, file ) );
return toStorageItem( path, file );
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( client, healthy );
}
}

@Override
public CompletableFuture<Void> downloadFileAsync( CloudURI source, Path destination ) {
public void downloadFile( CloudURI source, Path destination ) {
FTPClient client = borrow();
boolean healthy = false;
try {
oap.io.Files.ensureFile( destination );
try( OutputStream out = Files.newOutputStream( destination ) ) {
if( !client.retrieveFile( absolute( source.path ), out ) ) {
return CompletableFuture.failedFuture( new CloudException( "cannot download " + source ) );
throw new CloudException( "cannot download " + source );
}
}
healthy = true;
return CompletableFuture.completedFuture( null );
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( client, healthy );
}
}

@Override
public CompletableFuture<Void> copyAsync( CloudURI source, CloudURI destination ) {
public void copy( CloudURI source, CloudURI destination ) {
Preconditions.checkArgument( source.scheme.equals( destination.scheme ) );

FTPClient sourceClient = borrow();
Expand All @@ -360,7 +357,7 @@ public CompletableFuture<Void> copyAsync( CloudURI source, CloudURI destination
if( in == null ) {
sourceHealthy = true;
destinationHealthy = true;
return CompletableFuture.failedFuture( new CloudException( "cannot open source stream " + source ) );
throw new CloudException( "cannot open source stream " + source );
}

ensureRemoteDirectory( destinationClient, parentOf( absolute( destination.path ) ) );
Expand All @@ -373,31 +370,29 @@ public CompletableFuture<Void> copyAsync( CloudURI source, CloudURI destination
destinationHealthy = stored;

if( !stored || !completed ) {
return CompletableFuture.failedFuture( new CloudException( "cannot copy " + source + " to " + destination ) );
throw new CloudException( "cannot copy " + source + " to " + destination );
}

return CompletableFuture.completedFuture( null );
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( sourceClient, sourceHealthy );
release( destinationClient, destinationHealthy );
}
}

@Override
public CompletableFuture<? extends InputStream> getInputStreamAsync( CloudURI path ) {
public InputStream getInputStream( CloudURI path ) {
FTPClient client = borrow();
try {
InputStream in = client.retrieveFileStream( absolute( path.path ) );
if( in == null ) {
release( client, true );
return CompletableFuture.failedFuture( new CloudException( "cannot open " + path ) );
throw new CloudException( "cannot open " + path );
}
return CompletableFuture.completedFuture( new FtpInputStream( this, client, in ) );
return new FtpInputStream( this, client, in );
} catch( IOException e ) {
release( client, false );
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
}
}

Expand All @@ -420,7 +415,7 @@ public OutputStream getOutputStream( CloudURI path, Map<String, String> tags ) {
}

@Override
public CompletableFuture<Void> uploadAsync( CloudURI destination, BlobData blobData ) {
public void upload( CloudURI destination, BlobData blobData ) {
FTPClient client = borrow();
boolean healthy = false;
try {
Expand All @@ -447,20 +442,19 @@ public CompletableFuture<Void> uploadAsync( CloudURI destination, BlobData blobD
};

if( !stored ) {
return CompletableFuture.failedFuture( new CloudException( "cannot upload to " + destination ) );
throw new CloudException( "cannot upload to " + destination );
}

healthy = true;
return CompletableFuture.completedFuture( null );
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( client, healthy );
}
}

@Override
public CompletableFuture<PageSet<? extends FileSystem.StorageItem>> listAsync( CloudURI path, ListOptions listOptions ) {
public PageSet<? extends FileSystem.StorageItem> list( CloudURI path, ListOptions listOptions ) {
FTPClient client = borrow();
boolean healthy = false;
try {
Expand All @@ -482,9 +476,9 @@ public CompletableFuture<PageSet<? extends FileSystem.StorageItem>> listAsync( C
String nextToken = listOptions.maxKeys != null ? String.valueOf( skip + result.size() ) : null;

healthy = true;
return CompletableFuture.completedFuture( new PageSet<>( nextToken, result ) );
return new PageSet<>( nextToken, result );
} catch( IOException e ) {
return CompletableFuture.failedFuture( new CloudException( e ) );
throw new CloudException( e );
} finally {
release( client, healthy );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;
import static oap.testng.Asserts.assertFile;
Expand Down Expand Up @@ -134,8 +133,7 @@ public void testCopy() {
Files.write( path, "test string", ContentWriter.ofString() );

try( FileSystem fileSystem = new FileSystem( getFileSystemConfiguration() ) ) {
assertThat( fileSystem.copyAsync( fileSystem.toLocalFilePath( path ), new CloudURI( "file://logs/my-file.txt.gz" ), Map.of() ) )
.succeedsWithin( 30, TimeUnit.SECONDS );
fileSystem.copy( fileSystem.toLocalFilePath( path ), new CloudURI( "file://logs/my-file.txt.gz" ), Map.of() );

InputStream inputStream = fileSystem.getInputStream( new CloudURI( "file://logs/my-file.txt.gz" ) );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ public void testCopy() {
Files.write( path, "test string", ContentWriter.ofString() );

try( FileSystem fileSystem = new FileSystem( getFileSystemConfiguration() ) ) {
assertThat( fileSystem.copyAsync( fileSystem.toLocalFilePath( path ), new CloudURI( "ftp://logs/my-file.txt.gz" ), Map.of() ) )
.succeedsWithin( 30, TimeUnit.SECONDS );
fileSystem.copy( fileSystem.toLocalFilePath( path ), new CloudURI( "ftp://logs/my-file.txt.gz" ), Map.of() );

InputStream inputStream = fileSystem.getInputStream( new CloudURI( "ftp://logs/my-file.txt.gz" ) );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;
import static oap.io.content.ContentReader.ofString;
Expand Down Expand Up @@ -96,6 +95,32 @@ public void testGetOutputStream() throws IOException {
}
}

@Test
public void testGetOutputStreamMultipart() throws IOException {
int partSize = 5 * 1024 * 1024;
byte[] chunk = new byte[ 1024 * 1024 ];
for( int i = 0; i < chunk.length; i++ ) {
chunk[i] = ( byte ) ( 'a' + ( i % 26 ) );
}

int totalSize = partSize + chunk.length;

try( FileSystem fileSystem = new FileSystem( getFileSystemConfiguration() ) ) {
try( OutputStream outputStream = fileSystem.getOutputStream( new CloudURI( "s3://" + TEST_BUCKET + "/logs/big-file.bin" ), Map.of( "test-tag", "tag-val" ) ) ) {
int written = 0;
while( written < totalSize ) {
outputStream.write( chunk );
written += chunk.length;
}
}

assertThat( s3mockFixture.readTags( TEST_BUCKET, "logs/big-file.bin" ) ).contains( entry( "test-tag", "tag-val" ) );

byte[] content = s3mockFixture.readFile( TEST_BUCKET, "logs/big-file.bin", ContentReader.ofBytes(), Encoding.PLAIN );
assertThat( content.length ).isEqualTo( totalSize );
}
}

@Test
public void testGetMetadata() throws URISyntaxException {
Path path = testDirectoryFixture.testPath( "my-file.txt" );
Expand Down Expand Up @@ -133,8 +158,7 @@ public void testCopy() {
Files.write( path, "test string", ContentWriter.ofString() );

try( FileSystem fileSystem = new FileSystem( getFileSystemConfiguration() ) ) {
assertThat( fileSystem.copyAsync( fileSystem.toLocalFilePath( path ), new CloudURI( "s3://" + TEST_BUCKET + "/logs/my-file.txt.gz" ), Map.of( "tag1", "va1", "tag2", "val2" ) ) )
.succeedsWithin( 30, TimeUnit.SECONDS );
fileSystem.copy( fileSystem.toLocalFilePath( path ), new CloudURI( "s3://" + TEST_BUCKET + "/logs/my-file.txt.gz" ), Map.of( "tag1", "va1", "tag2", "val2" ) );

InputStream inputStream = fileSystem.getInputStream( new CloudURI( "s3://" + TEST_BUCKET + "/logs/my-file.txt.gz" ) );

Expand Down
4 changes: 2 additions & 2 deletions oap-storage/oap-storage-cloud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ CloudURI defaultUri = fs.getDefaultURL( "reports/today.json" );

### Operations reference

Every synchronous method has an `...Async` counterpart returning `CompletableFuture`.
All methods are synchronous/blocking.

| Method | Description |
|---|---|
Expand Down Expand Up @@ -159,7 +159,7 @@ s3=com.example.MyS3CloudApi

The class must have a constructor `(FileSystemConfiguration, String container)`.

Every method has a required `...Async(CloudURI, ...)` variant and a default synchronous wrapper that calls `.join()`.
Every method is a required synchronous, blocking method.

---

Expand Down
Loading
Loading