1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// --------------------------------------------------------------------------
//
// File
// Name: BackupStoreFileEncodeStream.h
// Purpose: Implement stream-based file encoding for the backup store
// Created: 12/1/04
//
// --------------------------------------------------------------------------
#ifndef BACKUPSTOREFILEENCODESTREAM__H
#define BACKUPSTOREFILEENCODESTREAM__H
#include <vector>
#include "IOStream.h"
#include "BackupStoreFilename.h"
#include "CollectInBufferStream.h"
#include "MD5Digest.h"
#include "BackupStoreFile.h"
#include "ReadLoggingStream.h"
#include "RunStatusProvider.h"
namespace BackupStoreFileCreation
{
// Diffing and creation of files share some implementation details.
typedef struct _BlocksAvailableEntry
{
struct _BlocksAvailableEntry *mpNextInHashList;
int32_t mSize; // size in clear
uint32_t mWeakChecksum; // weak, rolling checksum
uint8_t mStrongChecksum[MD5Digest::DigestLength]; // strong digest based checksum
} BlocksAvailableEntry;
}
// --------------------------------------------------------------------------
//
// Class
// Name: BackupStoreFileEncodeStream
// Purpose: Encode a file into a stream
// Created: 8/12/03
//
// --------------------------------------------------------------------------
class BackupStoreFileEncodeStream : public IOStream
{
public:
BackupStoreFileEncodeStream();
~BackupStoreFileEncodeStream();
typedef struct
{
int64_t mSpaceBefore; // amount of bytes which aren't taken out of blocks which go
int32_t mBlocks; // number of block to reuse, starting at this one
BackupStoreFileCreation::BlocksAvailableEntry *mpStartBlock; // may be null
} RecipeInstruction;
class Recipe : public std::vector<RecipeInstruction>
{
// NOTE: This class is rather tied in with the implementation of diffing.
public:
Recipe(BackupStoreFileCreation::BlocksAvailableEntry *pBlockIndex, int64_t NumBlocksInIndex,
int64_t OtherFileID = 0);
~Recipe();
int64_t GetOtherFileID() {return mOtherFileID;}
int64_t BlockPtrToIndex(BackupStoreFileCreation::BlocksAvailableEntry *pBlock)
{
return pBlock - mpBlockIndex;
}
private:
BackupStoreFileCreation::BlocksAvailableEntry *mpBlockIndex;
int64_t mNumBlocksInIndex;
int64_t mOtherFileID;
};
void Setup(const std::string& Filename, Recipe *pRecipe, int64_t ContainerID,
const BackupStoreFilename &rStoreFilename,
int64_t *pModificationTime,
ReadLoggingStream::Logger* pLogger = NULL,
RunStatusProvider* pRunStatusProvider = NULL,
BackgroundTask* pBackgroundTask = NULL);
virtual int Read(void *pBuffer, int NBytes, int Timeout);
virtual void Write(const void *pBuffer, int NBytes,
int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
int64_t GetBytesToUpload() { return mBytesToUpload; }
int64_t GetTotalBytesSent() { return mTotalBytesSent; }
static void CalculateBlockSizes(int64_t DataSize, int64_t &rNumBlocksOut,
int32_t &rBlockSizeOut, int32_t &rLastBlockSizeOut);
private:
enum
{
Status_Header = 0,
Status_Blocks = 1,
Status_BlockListing = 2,
Status_Finished = 3
};
void EncodeCurrentBlock();
void SkipPreviousBlocksInInstruction();
void SetForInstruction();
void StoreBlockIndexEntry(int64_t WncSizeOrBlkIndex, int32_t ClearSize, uint32_t WeakChecksum, uint8_t *pStrongChecksum);
Recipe *mpRecipe;
IOStream *mpFile; // source file
CollectInBufferStream mData; // buffer for header and index entries
IOStream *mpLogging;
RunStatusProvider* mpRunStatusProvider;
BackgroundTask* mpBackgroundTask;
int mStatus;
bool mSendData; // true if there's file data to send (ie not a symlink)
int64_t mTotalBlocks; // Total number of blocks in the file
int64_t mBytesToUpload; // Total number of clear bytes to encode and upload
int64_t mBytesUploaded; // Total number of clear bytes already encoded
// excluding reused blocks already on the server.
int64_t mAbsoluteBlockNumber; // The absolute block number currently being output
// Instruction number
int64_t mInstructionNumber;
// All the below are within the current instruction
int64_t mNumBlocks; // number of blocks. Last one will be a different size to the rest in most cases
int64_t mCurrentBlock;
int32_t mCurrentBlockEncodedSize;
int32_t mPositionInCurrentBlock; // for reading out
int32_t mBlockSize; // Basic block size of most of the blocks in the file
int32_t mLastBlockSize; // the size (unencoded) of the last block in the file
int64_t mTotalBytesSent;
// Buffers
uint8_t *mpRawBuffer; // buffer for raw data
BackupStoreFile::EncodingBuffer mEncodedBuffer;
// buffer for encoded data
int32_t mAllocatedBufferSize; // size of above two allocated blocks
uint64_t mEntryIVBase; // base for block entry IV
};
#endif // BACKUPSTOREFILEENCODESTREAM__H
|