Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial checkin for Storage file #4414

Merged
merged 33 commits into from
Jul 24, 2019

Conversation

sima-zhu
Copy link
Contributor

Linting, Junit test, builder refactor

@sima-zhu sima-zhu self-assigned this Jul 12, 2019
@sima-zhu sima-zhu added Storage Storage Service (Queues, Blobs, Files) Client This issue points to a problem in the data-plane of the library. labels Jul 12, 2019
@sima-zhu sima-zhu requested a review from alzimmermsft July 12, 2019 18:04
Copy link
Member

@alzimmermsft alzimmermsft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General question around the large model classes that were created, should they be simplified to only contain the most important pieces of information related to the service. If so remove the common HTTP headers as that information will still be available using the Response class headers.

@sima-zhu
Copy link
Contributor Author

General question around the large model classes that were created, should they be simplified to only contain the most important pieces of information related to the service. If so remove the common HTTP headers as that information will still be available using the Response class headers.

I have simplified the model class. Etag is the essential information we want to return.
I have get rid of the date, request id, and error part. Which field you think is also unnessary?

@sima-zhu sima-zhu requested a review from rickle-msft July 19, 2019 05:11
* @param directoryName Name of the directory
* @param snapshot The snapshot of the share
*/
DirectoryAsyncClient(AzureFileStorageImpl azureFileStorageClient, String shareName, String directoryName, String snapshot) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do all of our constructors create their own builders? This leads us to a code path where we create a builder to pass all the relevant info to the client which creates a new builder with the same info to compile the relevant info correctly for the client. We can probably remove these extra steps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sima - I still see the builder code that James is calling out. What has been done here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not push the commit at the time you reviewed. It is there right now. Could you check?

}

/**
* Creates a directory in the storage account and returns a response of {@link DirectoryInfo} to interact with it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convey that it creates the directory this client corresponds to, not just a directory. Also, the directory is technically created in the share. Two identical directory paths can exist in different shares. Perhaps Creates a directory in the storage account --> Creates this directory in the file share.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

public Mono<Response<DirectoryInfo>> setMetadata(Map<String, String> metadata) {
throw new UnsupportedOperationException();
/**
* Lists all directories and files in the storage account without their prefix or maxResult.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lists all directories and files in the storage account --> Lists all sub-directories and files in this directory
There are several instances where you scope the operation to the account, when it's really just to the contents of this directory. Be sure to address them. Additionally, double check the sync DirectoryClient for these issues as well.

* @param recursive Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files.
* @return {@link HandleItem handles} in the directory that satisfy the requirements
*/
public Flux<HandleItem> getHandles(Integer maxResult, boolean recursive) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxResult -> pageSize
While it's technically maxResult in REST, that's per paged request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to address this across all storage SDK

* @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles.
* @param recursive A boolean value that specifies if the operation should also apply to the files and subdirectories of the directory specified in the URI.
* @return The counts of number of handles closed
*/
public Flux<Integer> forceCloseHandles(String handleId, boolean recursive) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically correct according to the REST layer, but its usage is a bit flexible. For instance, handleId can be either the name of the handle to close, or *, meaning close all handles. Additionally, recursive doesn't make much sense if we've provided the specific handleId to close, and the REST endpoint actually has undefined behavior (unless they patched this) when both the wildcard and recursive=false are specified.

The way we handled this in track 1 was by exposing two different methods: forceCloseHandle(String handleId) and forceCloseAllHandles(boolean recursive), supplying the appropriate missing parameter. This allowed us to better guide users to what is expected use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue created.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an issue is created, link to if when you reference it so other interested people can find it and subscribe / offer comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linked the issue in Java doc

* @return A response containing the subdirectory client and the status of creating the directory.
* @throws StorageErrorException If the subdirectory has already existed, the parent directory does not exist or directory is an invalid resource name.
*/
public Mono<Response<DirectoryAsyncClient>> createSubDirectory(String subDirectoryName) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have this method call this.createSubDirectory(subDirectoryName, null). Same pattern we follow for overloads of service calls.

Similar comment for createFile().

Copy link
Contributor Author

@sima-zhu sima-zhu Jul 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*/
public Mono<Response<DirectoryAsyncClient>> createSubDirectory(String subDirectoryName, Map<String, String> metadata) {
String directoryPath = directoryName + "/" + subDirectoryName;
DirectoryAsyncClient createSubClient = new DirectoryAsyncClient(azureFileStorageClient, shareName, directoryPath, snapshot);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just call getSubDirectoryClient(). It's these exact lines.

Similar comment for createFile().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

public Mono<VoidResponse> deleteFile(String fileName) {
throw new UnsupportedOperationException();
String filePath = directoryName + "/" + fileName;
FileAsyncClient fileAsyncClient = new FileAsyncClient(azureFileStorageClient, shareName, filePath, snapshot);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before. We have methods for this logic. Just use them here and for deleting directories.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

this.sasTokenCredential = credential;
return this;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the credential method that takes a SharedKeyCredential?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

* @param snapshot Identifier of the snapshot
* @return the updated DirectoryClientBuilder object.
*/
public DirectoryClientBuilder snapshot(String snapshot) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably specify that this is a snapshot of the file share, not the directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

@JonathanGiles JonathanGiles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm seeing a lot of "done" comments that don't have the changes showing. I imagine this is because they haven't been pushed to GitHub. Please push the fixes, and consider my feedback, and then I will review again.


```Java
fileClient.setHttpHeaders(httpHeaders);
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will all these code samples be fleshed out? If not, I don't think they provide any value as single-line code samples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will make up some necessary code.
Thanks for reminding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has link in description which point to the place how we build a client.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will have more codes show how to build up the Object other than String type. e.g httpHeaders.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slf4j-api should come in transitively and not need to be included here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<scope>test</scope>
</dependency>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as in queues - is slf4j-simple, reactor-test, and adal4j required here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reactor-test is necessary for async tests.

Removed adal4j , slf4j-simple

* <ul>
* <li> If the HMAC-SHA256 signature for {@code sharedKeyCredentials} fails to generate. </li>
* <li> If the an invalid key has been given to the client. </li>
* </ul>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to the left.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

} catch (final NoSuchAlgorithmException e) {
throw new RuntimeException("There is no such algorithm. Error Details: " + e.getMessage());
} catch (InvalidKeyException e) {
throw new RuntimeException("Please double check the account key. Error details: " + e.getMessage());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use clientLogger logAndThrow API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log and throw API is not available to preview 2.
Issue opened. #4551

* <ul>
* <li> There is only one null value for retryDelay and maxRetryDelay.<li/>
* <li> Unrecognized retry policy type.<li/>
* </ul>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move left.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* @param directoryName Name of the directory
* @param snapshot The snapshot of the share
*/
DirectoryAsyncClient(AzureFileStorageImpl azureFileStorageClient, String shareName, String directoryName, String snapshot) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sima - I still see the builder code that James is calling out. What has been done here?

*
* {@codesnippet com.azure.storage.file.directoryAsyncClient.setMetadata#map.clearMetadata}
*
* @param metadata Optional. Metadata to set on the directory, if null is passed the metadata for the directory is cleared
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't write these as "Optional. Metadata ..." - make it a full sentence, e.g. "Optional metadata to set on the directory..".
Do this in all cases where the "Optional. " approach is being used currently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles.
* @param recursive A boolean value that specifies if the operation should also apply to the files and subdirectories of the directory specified in the URI.
* @return The counts of number of handles closed
*/
public Flux<Integer> forceCloseHandles(String handleId, boolean recursive) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an issue is created, link to if when you reference it so other interested people can find it and subscribe / offer comments.

Copy link
Member

@alzimmermsft alzimmermsft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving based on the major comments not being addressed in this PR being documented as issues.

Copy link
Member

@JonathanGiles JonathanGiles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the approval of Rick, James, and Alan, this PR doesn't need me to cast my eyes over it also.

<Match>
<Class name="~com\.azure\.(.+)Impl"/>
<Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE"/>
</Match>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't duplicate the pattern - put it in the Or clause above instead.

@sima-zhu sima-zhu merged commit 44fb56e into Azure:storage-post-review1-dev Jul 24, 2019
alzimmermsft added a commit that referenced this pull request Jul 25, 2019
* Storage SAS implementation (#4404)

* SAS implementation

* Fixed some minor formatting issues

* Fixed checkstyle problems and test issue

* Remove RawClients from Blobs (#4375)

Removes RawClients from Storage Blobs

* Add deleteContainer to StorageClient and getBlobClient with Snapshot to ContainerClient (#4376)

* Removed raw clients

* Added deleteContainer to StorageClient

* Added getAppendBlob with snapshot to ContainerClient

* Storage queue linting, builder refactor, tests (#4383)

* Initial check in for storage queue

* Initial checkin for Storage file (#4414)

* Finished the restructure, refactor builder. Added sleep in record feature. Linting

* Merge Storage Blob Client Builders (#4468)

Merges AppendBlobClientBuilder, BlobClientBuilder, BlockBlobClientBuilder, and PageBlobClientBuilder into a single builder class BlobClientBuilder. Additionally, JavaDoc comments for the other builder classes, ContainerClientBuilder and StorageAccountClientBuilder, were cleaned up and the way the endpoint is handled in builders was changed.
jianghaolu added a commit that referenced this pull request Jul 29, 2019
* Storage SAS implementation (#4404)

* SAS implementation

* Fixed some minor formatting issues

* Fixed checkstyle problems and test issue

* Remove RawClients from Blobs (#4375)

Removes RawClients from Storage Blobs

* Add storage swaggers

* Update Storage to azure-core preview 3

* Add deleteContainer to StorageClient and getBlobClient with Snapshot to ContainerClient (#4376)

* Removed raw clients

* Added deleteContainer to StorageClient

* Added getAppendBlob with snapshot to ContainerClient

* Storage queue linting, builder refactor, tests (#4383)

* Initial check in for storage queue

* Address code review feedback in AutoRest

* Initial checkin for Storage file (#4414)

* Finished the restructure, refactor builder. Added sleep in record feature. Linting

* Merge Storage Blob Client Builders (#4468)

Merges AppendBlobClientBuilder, BlobClientBuilder, BlockBlobClientBuilder, and PageBlobClientBuilder into a single builder class BlobClientBuilder. Additionally, JavaDoc comments for the other builder classes, ContainerClientBuilder and StorageAccountClientBuilder, were cleaned up and the way the endpoint is handled in builders was changed.

* Regenerate blob file queue after merge

* Up azure core version for file & queue

* Apply all the manual fixes in swagger

* Change directoryName to directoryPath

* Use non-fluent pattern for generated clients

* Fix build after merging with master

* Return void on setters

* Revert spotbugs config change
@sima-zhu sima-zhu deleted the storage-file branch February 23, 2021 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Client This issue points to a problem in the data-plane of the library. Storage Storage Service (Queues, Blobs, Files)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants