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 problem creating ZIP archive with lots of entries #2006

Merged
merged 2 commits into from
May 5, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/XrdCl/XrdClOperations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,32 @@ namespace XrdCl
final = std::move( f );
}

//------------------------------------------------------------------------
// Called by a pipeline on the handler of its first operation before Run
//------------------------------------------------------------------------
void PipelineHandler::PreparePipelineStart()
{
// Move any final-function from the handler of the last operaiton to the
// first. It will be moved along the pipeline of handlers while the
// pipeline is run.

if( final || !nextOperation ) return;
PipelineHandler *last = nextOperation->handler.get();
while( last )
{
Operation<true> *nextop = last->nextOperation.get();
if( !nextop ) break;
last = nextop->handler.get();
}
if( last )
{
// swap-then-move rather than only move as we need to guarantee that
// last->final is left without target.
std::function<void(const XRootDStatus&)> f;
f.swap( last->final );
Assign( std::move( f ) );
}
}

//------------------------------------------------------------------------
// Stop the current pipeline
Expand Down
9 changes: 9 additions & 0 deletions src/XrdCl/XrdClOperations.hh
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ namespace XrdCl
//------------------------------------------------------------------------
void Assign( std::function<void(const XRootDStatus&)> final );

//------------------------------------------------------------------------
//! Called by a pipeline on the handler of its first operation before Run
//------------------------------------------------------------------------
void PreparePipelineStart();

private:

//------------------------------------------------------------------------
Expand Down Expand Up @@ -487,6 +492,10 @@ namespace XrdCl
if( !operation ) std::logic_error( "Empty pipeline!" );

Operation<true> *opr = operation.release();
PipelineHandler *h = opr->handler.get();
if( h )
h->PreparePipelineStart();

opr->Run( timeout, std::move( prms ), std::move( final ) );
}

Expand Down
50 changes: 50 additions & 0 deletions src/XrdCl/XrdClUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -865,4 +865,54 @@ namespace XrdCl
if( dst_supported.count( *itr ) ) return *itr;
return std::string();
}

//----------------------------------------------------------------------------
//! Split chunks in a ChunkList into one or more ChunkLists
//----------------------------------------------------------------------------
void Utils::SplitChunks( std::vector<ChunkList> &listsvec,
const ChunkList &chunks,
const uint32_t maxcs,
const size_t maxc )
{
listsvec.clear();
if( !chunks.size() ) return;

listsvec.emplace_back();
ChunkList *c = &listsvec.back();
const size_t cs = chunks.size();
size_t idx = 0;
size_t nc = 0;
ChunkInfo tmpc;

c->reserve( cs );

while( idx < cs )
{
if( maxc && nc >= maxc )
{
listsvec.emplace_back();
c = &listsvec.back();
c->reserve( cs - idx );
nc = 0;
}

if( tmpc.length == 0 )
tmpc = chunks[idx];

if( maxcs && tmpc.length > maxcs )
{
c->emplace_back( tmpc.offset, maxcs, tmpc.buffer );
tmpc.offset += maxcs;
tmpc.length -= maxcs;
tmpc.buffer = static_cast<char*>( tmpc.buffer ) + maxcs;
}
else
{
c->emplace_back( tmpc.offset, tmpc.length, tmpc.buffer );
tmpc.length = 0;
++idx;
}
++nc;
}
}
}
12 changes: 12 additions & 0 deletions src/XrdCl/XrdClUtils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,18 @@ namespace XrdCl
if( !st.IsOK() ) return false;
return protver >= kXR_PROTPGRWVERSION;
}

//------------------------------------------------------------------------
//! Split chunks in a ChunkList into one or more ChunkLists
//! @param listsvec : output vector of ChunkLists
//! @param chunks : input ChunkLisits
//! @param maxcs : maximum size of a ChunkInfo in output
//! @param maxc : maximum number of ChunkInfo in each ChunkList
//------------------------------------------------------------------------
static void SplitChunks( std::vector<ChunkList> &listsvec,
const ChunkList &chunks,
const uint32_t maxcs,
const size_t maxc );
};

//----------------------------------------------------------------------------
Expand Down
13 changes: 11 additions & 2 deletions src/XrdCl/XrdClZipArchive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "XrdCl/XrdClLog.hh"
#include "XrdCl/XrdClDefaultEnv.hh"
#include "XrdCl/XrdClConstants.hh"
#include "XrdCl/XrdClUtils.hh"
#include "XrdZip/XrdZipZIP64EOCDL.hh"

#include <sys/stat.h>
Expand Down Expand Up @@ -626,10 +627,18 @@ namespace XrdCl
}

auto wrtbuff = std::make_shared<buffer_t>( GetCD() );
chunks.emplace_back( cdoff, wrtbuff->size(), wrtbuff->data() );
Pipeline p = XrdCl::Write( archive, cdoff,
wrtbuff->size(),
wrtbuff->data() );
wrtbufs.emplace_back( std::move( wrtbuff ) );

Pipeline p = XrdCl::VectorWrite( archive, chunks );
std::vector<ChunkList> listsvec;
XrdCl::Utils::SplitChunks( listsvec, chunks, 262144, 1024 );

for(auto itr = listsvec.rbegin(); itr != listsvec.rend(); ++itr)
{
p = XrdCl::VectorWrite( archive, *itr ) | p;
}
if( ckpinit )
p |= XrdCl::Checkpoint( archive, ChkPtCode::COMMIT );
p |= Close( archive ) >>
Expand Down