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

Fix s3 dirlisting to follow the istruncated/nextmarker #124

Merged
merged 2 commits into from
Jun 24, 2024
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
20 changes: 16 additions & 4 deletions src/fileops/davmeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ StatInfo & S3MetaOps::statInfo(IOChainContext & iocontext, StatInfo & st_info){

bool s3_get_next_property(std::unique_ptr<DirHandle> & handle, std::string & name_entry, StatInfo & info){
DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_CHAIN, " -> s3_get_next_property");
const size_t read_size = 2048;
const size_t read_size = 2048*1024;


HttpRequest& req = *(handle->request); // setup env again
Expand Down Expand Up @@ -1054,6 +1054,13 @@ void s3_start_listing_query(std::unique_ptr<DirHandle> & handle, Context & conte
}
else if(params->getS3ListingMode() == S3ListingMode::Hierarchical){
Uri new_url = S3::s3UriTransformer(url, params, true);
if (handle.get() != NULL) {
XMLPropParser & parser = *(handle->parser);
std::string nextmarker = parser.getNextMarker();
if (nextmarker != "") {
new_url.addQueryParam("marker", nextmarker);
}
}
handle.reset(new DirHandle(new GetRequest(context, new_url, &tmp_err), new S3PropParser(params->getS3ListingMode(), S3::extract_s3_path(url, params->getAwsAlternate()))));
}
else if(params->getS3ListingMode() == S3ListingMode::SemiHierarchical){
Expand Down Expand Up @@ -1087,10 +1094,10 @@ void s3_start_listing_query(std::unique_ptr<DirHandle> & handle, Context & conte

size_t prop_size = 0;
do{ // first entry -> bucket information
s_resu = incremental_listdir_parsing(&http_req, &parser, 2048, davix_scope_directory_listing_str());
s_resu = incremental_listdir_parsing(&http_req, &parser, 2048*1024, davix_scope_directory_listing_str());

prop_size = parser.getProperties().size();
if(s_resu < 2048 && prop_size <1){ // verify request status : if req done + no data -> error
if(s_resu < 2048*1024 && prop_size <1){ // verify request status : if req done + no data -> error
throw DavixException(davix_scope_directory_listing_str(), StatusCode::ParsingError, "Invalid server response, not a S3 listing");
}
if(timestamp_timeout < time(NULL)){
Expand All @@ -1113,8 +1120,13 @@ void s3_start_listing_query(std::unique_ptr<DirHandle> & handle, Context & conte


bool s3_directory_listing(std::unique_ptr<DirHandle> & handle, Context & context, const RequestParams* params, const Uri & uri, const std::string & body, std::string & name_entry, StatInfo & info){
if(handle.get() == NULL){
if (handle.get() == NULL){
s3_start_listing_query(handle, context, params, uri, body);
} else {
XMLPropParser& parser = *(handle->parser);
if (parser.getProperties().empty() && !parser.getNextMarker().empty()) {
s3_start_listing_query(handle, context, params, uri, body);
}
}
return s3_get_next_property(handle, name_entry, info);
}
Expand Down
1 change: 1 addition & 0 deletions src/xml/davxmlparser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class ElementsParser {
virtual ~ElementsParser(){}

virtual std::deque<FileProperties> & getProperties()=0;
virtual std::string getNextMarker() { return ""; };

};

Expand Down
22 changes: 22 additions & 0 deletions src/xml/s3propparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const std::string prefix_prop = "Prefix";
const std::string com_prefix_prop = "CommonPrefixes";
const std::string listbucketresult_prop = "ListBucketResult";
const std::string last_modified_prop = "LastModified";
const std::string istruncated_prop = "IsTruncated";
const std::string nextmarker_prop = "NextMarker";

struct S3PropParser::Internal{
std::string current;
Expand All @@ -50,6 +52,9 @@ struct S3PropParser::Internal{
FileProperties property;
S3ListingMode::S3ListingMode _s3_listing_mode;

bool istruncated = false;
std::string nextmarker = "";

int start_elem(const std::string &elem){
// new tag, clean content;
current.clear();
Expand Down Expand Up @@ -111,6 +116,9 @@ struct S3PropParser::Internal{
property.info.mode &= ~(S_IFREG);
props.push_back(property);
prop_count++;
if (istruncated) {
nextmarker = current;
}
}
}

Expand Down Expand Up @@ -190,6 +198,16 @@ struct S3PropParser::Internal{
throw DavixException(davix_scope_directory_listing_str(), StatusCode::IsNotADirectory, "Not a S3 directory");
}

// IsTruncated
if( (_s3_listing_mode == S3ListingMode::Hierarchical) && (StrUtil::compare_ncase(istruncated_prop, elem) ==0)){
istruncated = (current == "True" || current == "true");
}

// NextMarker
if( (_s3_listing_mode == S3ListingMode::Hierarchical) && (StrUtil::compare_ncase(nextmarker_prop, elem) ==0)){
nextmarker = current;
}

// reduce stack size
if(stack_status.size() > 0)
stack_status.pop();
Expand Down Expand Up @@ -252,5 +270,9 @@ std::deque<FileProperties> & S3PropParser::getProperties(){
return d_ptr->props;
}

std::string S3PropParser::getNextMarker() {
return (d_ptr->istruncated ? d_ptr->nextmarker : "");
}


}
1 change: 1 addition & 0 deletions src/xml/s3propparser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class S3PropParser : public XMLPropParser
virtual ~S3PropParser();

virtual std::deque<FileProperties> & getProperties();
virtual std::string getNextMarker();


protected:
Expand Down