xref: /haiku/src/add-ons/kernel/file_systems/ramfs/DataContainer.h (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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