1// DataContainer.h 2 3#ifndef DATA_CONTAINER_H 4#define DATA_CONTAINER_H 5 6#include "List.h" 7 8class AllocationInfo; 9class BlockReference; 10class Volume; 11 12// Size of the DataContainer's small buffer. If it contains data up to this 13// size, no blocks are allocated, but the small buffer is used instead. 14// 16 bytes are for free, since they are shared with the block list. 15// (actually even more, since the list has an initial size). 16// I ran a test analyzing what sizes the attributes in my system have: 17// size percentage bytes used in average 18// <= 0 0.00 93.45 19// <= 4 25.46 75.48 20// <= 8 30.54 73.02 21// <= 16 52.98 60.37 22// <= 32 80.19 51.74 23// <= 64 94.38 70.54 24// <= 126 96.90 128.23 25// 26// For average memory usage it is assumed, that attributes larger than 126 27// bytes have size 127, that the list has an initial capacity of 10 entries 28// (40 bytes), that the block reference consumes 4 bytes and the block header 29// 12 bytes. The optimal length is actually 35, with 51.05 bytes per 30// attribute, but I conservatively rounded to 32. 31static const size_t kSmallDataContainerSize = 32; 32 33class DataContainer { 34public: 35 DataContainer(Volume *volume); 36 virtual ~DataContainer(); 37 38 status_t InitCheck() const; 39 40 Volume *GetVolume() const { return fVolume; } 41 42 status_t Resize(off_t newSize); 43 off_t GetSize() const { return fSize; } 44 45 virtual status_t ReadAt(off_t offset, void *buffer, size_t size, 46 size_t *bytesRead); 47 virtual status_t WriteAt(off_t offset, const void *buffer, size_t size, 48 size_t *bytesWritten); 49 50 void GetFirstDataBlock(const uint8 **data, size_t *length); 51 52 // debugging 53 void GetAllocationInfo(AllocationInfo &info); 54 55private: 56 typedef List<BlockReference*> BlockList; 57 58private: 59 static inline bool _RequiresBlockMode(size_t size); 60 inline bool _IsBlockMode() const; 61 62 inline BlockList *_GetBlockList(); 63 inline const BlockList *_GetBlockList() const; 64 inline int32 _CountBlocks() const; 65 inline void *_GetBlockDataAt(int32 index, size_t offset, size_t size); 66 67 void _ClearArea(off_t offset, off_t size); 68 69 status_t _Resize(off_t newSize); 70 status_t _ResizeLastBlock(size_t newSize); 71 72 status_t _SwitchToBlockMode(size_t newBlockSize); 73 void _SwitchToSmallBufferMode(size_t newSize); 74 75private: 76 Volume *fVolume; 77 off_t fSize; 78 union { 79 uint8 fBlocks[sizeof(BlockList)]; 80 uint8 fSmallBuffer[kSmallDataContainerSize]; 81 }; 82}; 83 84#endif // DATA_CONTAINER_H 85