2014-12-11 10:50:15 +03:00
|
|
|
// Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> and ZBackup contributors, see CONTRIBUTORS
|
2014-11-27 19:20:41 +03:00
|
|
|
// Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE
|
|
|
|
|
2014-12-15 14:13:34 +03:00
|
|
|
#include "backup_collector.hh"
|
2014-11-27 19:20:41 +03:00
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
void BundleCollector::startIndex( string const & indexFn )
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-08-12 16:27:54 +03:00
|
|
|
indexModified = indexNecessary = false;
|
2015-02-04 14:38:22 +03:00
|
|
|
indexTotalChunks = indexUsedChunks = 0;
|
|
|
|
indexModifiedBundles = indexKeptBundles = indexRemovedBundles = 0;
|
|
|
|
}
|
2014-11-27 19:20:41 +03:00
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
void BundleCollector::finishIndex( string const & indexFn )
|
|
|
|
{
|
|
|
|
if ( indexModified )
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-08-04 16:03:51 +03:00
|
|
|
verbosePrintf( "Chunks used: %d/%d, bundles: %d kept, %d modified, %d removed\n",
|
|
|
|
indexUsedChunks, indexTotalChunks, indexKeptBundles,
|
2015-08-18 17:27:27 +03:00
|
|
|
indexModifiedBundles, indexRemovedBundles );
|
2015-02-04 14:38:22 +03:00
|
|
|
filesToUnlink.push_back( indexFn );
|
2015-08-04 16:03:51 +03:00
|
|
|
commit();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
chunkStorageWriter->reset();
|
2015-08-18 17:27:27 +03:00
|
|
|
if ( !indexNecessary )
|
|
|
|
// this index was a complete copy so we don't need it
|
2015-08-12 16:27:54 +03:00
|
|
|
filesToUnlink.push_back( indexFn );
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|
2015-02-04 14:38:22 +03:00
|
|
|
}
|
2014-11-27 19:20:41 +03:00
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
void BundleCollector::startBundle( Bundle::Id const & bundleId )
|
|
|
|
{
|
|
|
|
savedId = bundleId;
|
|
|
|
totalChunks = 0;
|
|
|
|
usedChunks = 0;
|
|
|
|
}
|
2014-11-27 19:20:41 +03:00
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
void BundleCollector::processChunk( ChunkId const & chunkId )
|
|
|
|
{
|
2015-08-18 17:27:27 +03:00
|
|
|
if ( overallChunkSet.find ( chunkId ) == overallChunkSet.end() )
|
|
|
|
overallChunkSet.insert( chunkId );
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
totalChunks++;
|
|
|
|
if ( usedChunkSet.find( chunkId ) != usedChunkSet.end() )
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-02-04 14:38:22 +03:00
|
|
|
usedChunks++;
|
2015-08-12 16:27:54 +03:00
|
|
|
indexNecessary = true;
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|
2015-02-04 14:38:22 +03:00
|
|
|
}
|
2014-11-27 19:20:41 +03:00
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
void BundleCollector::finishBundle( Bundle::Id const & bundleId, BundleInfo const & info )
|
|
|
|
{
|
|
|
|
string i = Bundle::generateFileName( savedId, "", false );
|
|
|
|
indexTotalChunks += totalChunks;
|
|
|
|
indexUsedChunks += usedChunks;
|
2015-08-12 16:27:54 +03:00
|
|
|
if ( 0 == usedChunks && 0 != totalChunks )
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-08-12 16:27:54 +03:00
|
|
|
dPrintf( "Deleting %s bundle\n", i.c_str() );
|
2015-02-04 14:38:22 +03:00
|
|
|
filesToUnlink.push_back( Dir::addPath( bundlesPath, i ) );
|
|
|
|
indexModified = true;
|
|
|
|
indexRemovedBundles++;
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|
2015-02-04 14:38:22 +03:00
|
|
|
else if ( usedChunks < totalChunks )
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-08-12 16:27:54 +03:00
|
|
|
dPrintf( "%s: used %d/%d chunks\n", i.c_str(), usedChunks, totalChunks );
|
2015-02-04 14:38:22 +03:00
|
|
|
filesToUnlink.push_back( Dir::addPath( bundlesPath, i ) );
|
|
|
|
indexModified = true;
|
2015-08-18 17:27:27 +03:00
|
|
|
copyUsedChunks( info );
|
2015-02-04 14:38:22 +03:00
|
|
|
indexModifiedBundles++;
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|
2015-02-04 14:38:22 +03:00
|
|
|
else
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-08-18 17:27:27 +03:00
|
|
|
if ( !deepGC )
|
|
|
|
{
|
|
|
|
chunkStorageWriter->addBundle( info, savedId );
|
|
|
|
dPrintf( "Keeping %s bundle\n", i.c_str() );
|
|
|
|
indexKeptBundles++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
filesToUnlink.push_back( Dir::addPath( bundlesPath, i ) );
|
|
|
|
indexModified = true;
|
|
|
|
copyUsedChunks( info );
|
|
|
|
indexModifiedBundles++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BundleCollector::copyUsedChunks( BundleInfo const & info )
|
|
|
|
{
|
|
|
|
// Copy used chunks to the new index
|
|
|
|
string chunk;
|
|
|
|
size_t chunkSize;
|
|
|
|
for ( int x = info.chunk_record_size(); x--; )
|
|
|
|
{
|
|
|
|
BundleInfo_ChunkRecord const & record = info.chunk_record( x );
|
|
|
|
ChunkId id( record.id() );
|
|
|
|
if ( usedChunkSet.find( id ) != usedChunkSet.end() )
|
|
|
|
{
|
|
|
|
chunkStorageReader->get( id, chunk, chunkSize );
|
|
|
|
chunkStorageWriter->add( id, chunk.data(), chunkSize );
|
|
|
|
}
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-04 14:38:22 +03:00
|
|
|
void BundleCollector::commit()
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-02-04 14:38:22 +03:00
|
|
|
for ( int i = filesToUnlink.size(); i--; )
|
2014-11-27 19:20:41 +03:00
|
|
|
{
|
2015-08-12 16:27:54 +03:00
|
|
|
dPrintf( "Unlinking %s\n", filesToUnlink[i].c_str() );
|
2015-02-04 14:38:22 +03:00
|
|
|
unlink( filesToUnlink[i].c_str() );
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|
2015-02-04 14:38:22 +03:00
|
|
|
filesToUnlink.clear();
|
|
|
|
chunkStorageWriter->commit();
|
2014-11-27 19:20:41 +03:00
|
|
|
}
|