summaryrefslogtreecommitdiff
path: root/lib/backupstore/BackupStoreFileEncodeStream.h
blob: 023994afb3b574b82a0eeb42d17d6ca761bf10bc (plain)
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
// --------------------------------------------------------------------------
//
// 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 char *Filename, Recipe *pRecipe, int64_t ContainerID,
		const BackupStoreFilename &rStoreFilename,
		int64_t *pModificationTime,
		ReadLoggingStream::Logger* pLogger = NULL,
		RunStatusProvider* pRunStatusProvider = NULL);

	virtual int Read(void *pBuffer, int NBytes, int Timeout);
	virtual void Write(const void *pBuffer, int NBytes);
	virtual bool StreamDataLeft();
	virtual bool StreamClosed();
	int64_t GetTotalBytesSent() { return mTotalBytesSent; }

private:
	enum
	{
		Status_Header = 0,
		Status_Blocks = 1,
		Status_BlockListing = 2,
		Status_Finished = 3
	};
	
private:
	void EncodeCurrentBlock();
	void CalculateBlockSizes(int64_t DataSize, int64_t &rNumBlocksOut, int32_t &rBlockSizeOut, int32_t &rLastBlockSizeOut);
	void SkipPreviousBlocksInInstruction();
	void SetForInstruction();
	void StoreBlockIndexEntry(int64_t WncSizeOrBlkIndex, int32_t ClearSize, uint32_t WeakChecksum, uint8_t *pStrongChecksum);

private:
	Recipe *mpRecipe;
	IOStream *mpFile;					// source file
	CollectInBufferStream mData;		// buffer for header and index entries
	IOStream *mpLogging;
	RunStatusProvider* mpRunStatusProvider;
	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 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