xref: /haiku/headers/private/package/hpkg/PackageFileHeapAccessorBase.h (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_
6 #define _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_
7 
8 
9 #include <new>
10 
11 #include <Referenceable.h>
12 
13 #include <CompressionAlgorithm.h>
14 #include <package/hpkg/DataReader.h>
15 
16 
17 namespace BPackageKit {
18 
19 namespace BHPKG {
20 
21 
22 class BErrorOutput;
23 
24 
25 namespace BPrivate {
26 
27 
28 template<typename Parameters>
29 struct GenericCompressionAlgorithmOwner : BReferenceable {
30 	BCompressionAlgorithm*	algorithm;
31 	Parameters*				parameters;
32 
33 	GenericCompressionAlgorithmOwner(BCompressionAlgorithm* algorithm,
34 		Parameters* parameters)
35 		:
36 		algorithm(algorithm),
37 		parameters(parameters)
38 	{
39 	}
40 
41 	~GenericCompressionAlgorithmOwner()
42 	{
43 		delete algorithm;
44 		delete parameters;
45 	}
46 
47 	static GenericCompressionAlgorithmOwner* Create(
48 		BCompressionAlgorithm* algorithm, Parameters* parameters)
49 	{
50 		GenericCompressionAlgorithmOwner* owner
51 			= new(std::nothrow) GenericCompressionAlgorithmOwner(algorithm,
52 				parameters);
53 		if (owner == NULL) {
54 			delete algorithm;
55 			delete parameters;
56 		}
57 
58 		return owner;
59 	}
60 };
61 
62 typedef GenericCompressionAlgorithmOwner<BCompressionParameters>
63 	CompressionAlgorithmOwner;
64 typedef GenericCompressionAlgorithmOwner<BDecompressionParameters>
65 	DecompressionAlgorithmOwner;
66 
67 
68 class PackageFileHeapAccessorBase : public BAbstractBufferedDataReader {
69 public:
70 			class OffsetArray;
71 
72 public:
73 								PackageFileHeapAccessorBase(
74 									BErrorOutput* errorOutput,
75 									BPositionIO* file, off_t heapOffset,
76 									DecompressionAlgorithmOwner*
77 										decompressionAlgorithm);
78 	virtual						~PackageFileHeapAccessorBase();
79 
80 			off_t				HeapOffset() const
81 									{ return fHeapOffset; }
82 			off_t				CompressedHeapSize() const
83 									{ return fCompressedHeapSize; }
84 			uint64				UncompressedHeapSize() const
85 									{ return fUncompressedHeapSize; }
86 			size_t				ChunkSize() const
87 									{ return kChunkSize; }
88 
89 			// normally used after cloning a PackageFileHeapReader only
90 			void				SetErrorOutput(BErrorOutput* errorOutput)
91 									{ fErrorOutput = errorOutput; }
92 			void				SetFile(BPositionIO* file)
93 									{ fFile = file; }
94 
95 	// BAbstractBufferedDataReader
96 	virtual	status_t			ReadDataToOutput(off_t offset,
97 									size_t size, BDataIO* output);
98 
99 public:
100 	static	const size_t		kChunkSize = 64 * 1024;
101 #if defined(_KERNEL_MODE)
102 	static	void*				sChunkCache;
103 #endif
104 
105 protected:
106 	virtual	status_t			ReadAndDecompressChunk(size_t chunkIndex,
107 									void* compressedDataBuffer,
108 									void* uncompressedDataBuffer) = 0;
109 			status_t			ReadAndDecompressChunkData(uint64 offset,
110 									size_t compressedSize,
111 									size_t uncompressedSize,
112 									void* compressedDataBuffer,
113 									void* uncompressedDataBuffer);
114 			status_t			DecompressChunkData(
115 									void* compressedDataBuffer,
116 									size_t compressedSize,
117 									void* uncompressedDataBuffer,
118 									size_t uncompressedSize);
119 			status_t			ReadFileData(uint64 offset, void* buffer,
120 									size_t size);
121 
122 protected:
123 			BErrorOutput*		fErrorOutput;
124 			BPositionIO*		fFile;
125 			off_t				fHeapOffset;
126 			uint64				fCompressedHeapSize;
127 			uint64				fUncompressedHeapSize;
128 			DecompressionAlgorithmOwner* fDecompressionAlgorithm;
129 };
130 
131 
132 /*!	Stores the chunk offsets in a compact way, while still providing quick
133 	access.
134 	- The object doesn't store the number of chunks/offsets it contains. During
135 	  initialization the chunk count is provided. Later, when getting an offset,
136 	  the caller is responsible for ensuring a valid index.
137 	- The first (index 0) chunk offset is omitted, since it is always 0.
138 	- The chunk offsets that fit in a 32 bit number use only one 32 bit element
139 	  in the offsets array.
140 	- The chunk offsets that don't fit in a 32 bit number use two elements in
141 	  the offsets array.
142 	Memory use is one pointer, if the chunk count is <= 1 (uncompressed heap size
143 	<= 64 KiB). Afterwards it's one pointer plus 32 bit per chunk as long as the
144 	last offset still fits 32 bit (compressed heap size < 4GiB). For any further
145 	chunks it is 64 bit per chunk. So, for the common case we use sizeof(void*)
146 	plus 1 KiB per 16 MiB of uncompressed heap, or about 64 KiB per 1 GiB. Which
147 	seems reasonable for packagefs to keep in memory.
148  */
149 class PackageFileHeapAccessorBase::OffsetArray {
150 public:
151 								OffsetArray();
152 								~OffsetArray();
153 
154 			bool				InitUncompressedChunksOffsets(
155 									size_t totalChunkCount);
156 			bool				InitChunksOffsets(size_t totalChunkCount,
157 									size_t baseIndex, const uint16* chunkSizes,
158 									size_t chunkCount);
159 
160 			bool				Init(size_t totalChunkCount,
161 									const OffsetArray& other);
162 									// "copy" init
163 
164 			uint64				operator[](size_t index) const;
165 
166 private:
167 	static	uint32*				_AllocateOffsetArray(size_t totalChunkCount,
168 									size_t offset32BitChunkCount);
169 
170 private:
171 			uint32*				fOffsets;
172 									// - NULL, if chunkCount <= 1
173 									// - element 0 contains the number of 32 bit
174 									//   offsets that follow, or is 0, when all
175 									//   offsets are 32 bit only
176 									// - the following offsets use two elements
177 									//   each (lower followed by upper 32 bit)
178 									//   to represent the 64 bit value
179 };
180 
181 
182 inline uint64
183 PackageFileHeapAccessorBase::OffsetArray::operator[](size_t index) const
184 {
185 	if (index == 0)
186 		return 0;
187 
188 	if (fOffsets[0] == 0 || index < fOffsets[0])
189 		return fOffsets[index];
190 
191 	index += index - fOffsets[0];
192 	return fOffsets[index] | ((uint64)fOffsets[index + 1] << 32);
193 }
194 
195 
196 }	// namespace BPrivate
197 
198 }	// namespace BHPKG
199 
200 }	// namespace BPackageKit
201 
202 
203 #endif	// _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_
204