forked from linkedin/ambry
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add S3MultipartETag class with version control (linkedin#2739)
Add S3MultipartETag class with version control.
- Loading branch information
1 parent
4a4ee68
commit 2ec5676
Showing
7 changed files
with
220 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
ambry-api/src/main/java/com/github/ambry/frontend/s3/S3MultipartETag.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Copyright 2024 LinkedIn Corp. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* | ||
*/ | ||
package com.github.ambry.frontend.s3; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.github.ambry.frontend.PutBlobMetaInfo; | ||
import com.github.ambry.utils.Pair; | ||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
|
||
/** | ||
* This class holds ETag returned for the Multipart part upload. | ||
* json example: | ||
* { | ||
* "dataChunkList": { | ||
* "chunks": [ | ||
* { | ||
* "blob": "AAYQ_3Z6AAoAAQAAAAAAAAAHyAWDw-xvSHWPD608xUQH3w", | ||
* "size": 8024 | ||
* }, | ||
* { | ||
* "blob": "AAYQ_3Z6ACWBADERGGGGGVVDASDEG-xv8xUQH3wAHyAWDw", | ||
* "size": 4031 | ||
* } | ||
* ], | ||
* "reservedMetadataChunkId": null | ||
* }, | ||
* "version": 1 | ||
* } | ||
*/ | ||
public class S3MultipartETag { | ||
static final short VERSION_1 = 1; | ||
static short CURRENT_VERSION = VERSION_1; | ||
private static final String VERSION = "version"; | ||
private static final String DATA_CHUNK_LIST = "dataChunkList"; | ||
private final List<Pair<String, Long>> orderedChunkIdSizeList; | ||
private short version; | ||
|
||
private static final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
||
/** | ||
* Construct S3MultipartETag | ||
* @param orderedChunkIdSizeList data chunk id and size list in order | ||
*/ | ||
public S3MultipartETag(List<Pair<String, Long>> orderedChunkIdSizeList) { | ||
version = CURRENT_VERSION; | ||
this.orderedChunkIdSizeList = orderedChunkIdSizeList; | ||
} | ||
|
||
/** | ||
* Get the version number | ||
* @return the version | ||
*/ | ||
public short getVersion() { | ||
return version; | ||
} | ||
|
||
/** | ||
* Get the data chunk list in order | ||
* @return the data chunk id/size list | ||
*/ | ||
public List<Pair<String, Long>> getOrderedChunkIdSizeList() { | ||
return orderedChunkIdSizeList; | ||
} | ||
|
||
/** | ||
* Serialize the {@link S3MultipartETag} to Json string | ||
* @return the serialized Json string | ||
*/ | ||
public static String serialize(S3MultipartETag eTag) throws IOException { | ||
ObjectNode rootObject = objectMapper.createObjectNode(); | ||
|
||
PutBlobMetaInfo metaInfo = new PutBlobMetaInfo(eTag.getOrderedChunkIdSizeList(), null); | ||
ObjectNode chunks = PutBlobMetaInfo.serializeToJsonObject(metaInfo); | ||
rootObject.put(DATA_CHUNK_LIST, chunks); | ||
rootObject.put(VERSION, CURRENT_VERSION); | ||
|
||
return rootObject.toString(); | ||
} | ||
|
||
/** | ||
* Deserialize the Json String to {@link S3MultipartETag} | ||
* @return the {@link S3MultipartETag} | ||
*/ | ||
public static S3MultipartETag deserialize(String eTagStr) throws IOException { | ||
JsonNode rootNode; | ||
try { | ||
rootNode = objectMapper.readTree(eTagStr); | ||
} catch (JsonProcessingException e) { | ||
throw new IOException("Not expected JSON content " + eTagStr + e.getMessage()); | ||
} | ||
|
||
// version id | ||
JsonNode jsonNode = rootNode.get(VERSION); | ||
short version = jsonNode.shortValue(); | ||
if (version != VERSION_1) { | ||
throw new IOException("Wrong version number " + eTagStr); | ||
} | ||
|
||
// data chunk list | ||
jsonNode = rootNode.get(DATA_CHUNK_LIST); | ||
PutBlobMetaInfo putBlobMetaInfo = PutBlobMetaInfo.deserialize(jsonNode.toString()); | ||
return new S3MultipartETag(putBlobMetaInfo.getOrderedChunkIdSizeList()); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
|
||
S3MultipartETag other = (S3MultipartETag) o; | ||
|
||
return version == other.version && Objects.equals(orderedChunkIdSizeList, other.orderedChunkIdSizeList); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters