1 // DataContainer.h 2 3 #ifndef DATA_CONTAINER_H 4 #define DATA_CONTAINER_H 5 6 #include "List.h" 7 8 class AllocationInfo; 9 class BlockReference; 10 class 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. 31 static const size_t kSmallDataContainerSize = 32; 32 33 class DataContainer { 34 public: 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 55 private: 56 typedef List<BlockReference*> BlockList; 57 58 private: 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 75 private: 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