1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef SHARED_BLOCK_H
17 #define SHARED_BLOCK_H
18 
19 #include <cinttypes>
20 
21 #include <string>
22 #include <ashmem.h>
23 #include "message_parcel.h"
24 #include "parcel.h"
25 #include "securec.h"
26 #include "rdb_visibility.h"
27 
28 namespace OHOS {
29 namespace AppDataFwk {
30 /**
31  * @brief The constant indicates the error is due to an invalid row record.
32  */
33 static const uint32_t INVALID_ROW_RECORD = 0xFFFFFFFF;
34 /**
35  * This class stores a set of rows from a database in a buffer,
36  * which is used as the set of query result.
37  */
38 class API_EXPORT SharedBlock {
39 public:
40     /**
41      * @brief Cell Unit types.
42      */
43     enum {
44         /** Indicates the Cell Unit data type is NULL at the specified row and column.*/
45         CELL_UNIT_TYPE_NULL = 0,
46         /** Indicates the current Cell Unit data type is INT at the specified row and column.*/
47         CELL_UNIT_TYPE_INTEGER = 1,
48         /** Indicates the current Cell Unit data type is FLOAT at the specified row and column.*/
49         CELL_UNIT_TYPE_FLOAT = 2,
50         /** Indicates the current Cell Unit data type is STRING at the specified row and column.*/
51         CELL_UNIT_TYPE_STRING = 3,
52         /** Indicates the current Cell Unit data type is BLOB at the specified row and column.*/
53         CELL_UNIT_TYPE_BLOB = 4,
54         /** Indicates the current Cell Unit data type is Asset at the specified row and column.*/
55         CELL_UNIT_TYPE_ASSET = 5,
56         /** Indicates the current Cell Unit data type is Assets at the specified row and column.*/
57         CELL_UNIT_TYPE_ASSETS = 6,
58         /** Indicates the current Cell Unit data type is vector<float> at the specified row and column.*/
59         CELL_UNIT_TYPE_FLOATS = 7,
60         /** Indicates the current Cell Unit data type is bigint at the specified row and column.*/
61         CELL_UNIT_TYPE_BIGINT = 8,
62     };
63 
64     /**
65      * @brief SharedBlock error types.
66      */
67     enum {
68         /** Indicates that the operation on SHARED BLOCK was successful.*/
69         SHARED_BLOCK_OK = 0,
70         /** Indicates that the result returned by the shared block operation is a bad value.*/
71         SHARED_BLOCK_BAD_VALUE = 1,
72         /** Indicates the current shared block space is not enough.*/
73         SHARED_BLOCK_NO_MEMORY = 2,
74         /** Indicates that the current operation on SHARED BLOCK is invalid.*/
75         SHARED_BLOCK_INVALID_OPERATION = 3,
76         /** Indicates that an ashmem error occurred in the operation of shared memory.*/
77         SHARED_BLOCK_ASHMEM_ERROR = 4,
78         /** Indicates that the set port error occurred in the operation of shared memory.*/
79         SHARED_BLOCK_SET_PORT_ERROR = 5,
80     };
81 
82     /**
83      * Cell Unit
84      * */
85     struct CellUnit {
86         int32_t type;
87         union {
88             double doubleValue;
89             int64_t longValue;
90             struct {
91                 uint32_t offset;
92                 uint32_t size;
93             } stringOrBlobValue;
94         } cell;
95         API_EXPORT std::string GetString(SharedBlock *block) const;
96         API_EXPORT std::vector<uint8_t> GetBlob(SharedBlock *block) const;
97         API_EXPORT const uint8_t *GetRawData(SharedBlock *block) const;
98     } __attribute((packed));
99 
100     /**
101      * @brief Constructor.
102      */
103     API_EXPORT SharedBlock(const std::string &name, sptr<Ashmem> ashmem, size_t size, bool readOnly);
104 
105     /**
106      * @brief Destructor.
107      */
108     API_EXPORT ~SharedBlock();
109 
110     /**
111      * @brief Init current shared block.
112      */
113     API_EXPORT bool Init();
114 
115     /**
116      * @brief Create a shared block.
117      */
118     API_EXPORT static int Create(const std::string &name, size_t size, SharedBlock *&outSharedBlock);
119 
120     /**
121      * @brief Clear current shared block.
122      */
123     API_EXPORT int Clear();
124 
125     /**
126      * @brief Set a shared block column.
127      */
128     API_EXPORT int SetColumnNum(uint32_t numColumns);
129 
130     /**
131      * @brief Allocate a row unit and its directory.
132      */
133     API_EXPORT int AllocRow();
134 
135     /**
136      * @brief Release the value of the last row.
137      */
138     API_EXPORT int FreeLastRow();
139 
140     /**
141      * @brief Put blob data to the shared block.
142      */
143     API_EXPORT int PutBlob(uint32_t row, uint32_t column, const void *value, size_t Size);
144 
145     /**
146      * @brief Put string data to the shared block.
147      */
148     API_EXPORT int PutString(uint32_t row, uint32_t column, const char *value, size_t sizeIncludingNull);
149 
150     /**
151      * @brief Put long data to the shared block.
152      */
153     API_EXPORT int PutLong(uint32_t row, uint32_t column, int64_t value);
154 
155     /**
156      * @brief Put Double data to the shared block.
157      */
158     API_EXPORT int PutDouble(uint32_t row, uint32_t column, double value);
159 
160     /**
161      * @brief Put Asset data to the shared block.
162      */
163     API_EXPORT int PutAsset(uint32_t row, uint32_t column, const void *value, size_t size);
164 
165     /**
166      * @brief Put Assets data to the shared block.
167      */
168     API_EXPORT int PutAssets(uint32_t row, uint32_t column, const void *value, size_t size);
169 
170     /**
171      * @brief Put vector<float> data to the shared block.
172      */
173     API_EXPORT int PutFloats(uint32_t row, uint32_t column, const void *value, size_t size);
174 
175     /**
176      * @brief Put BigInt data to the shared block.
177      */
178     API_EXPORT int PutBigInt(uint32_t row, uint32_t column, const void *value, size_t size);
179 
180     /**
181      * @brief Put Null data to the shared block.
182      */
183     API_EXPORT int PutNull(uint32_t row, uint32_t column);
184 
185     /**
186      * @brief Obtains the cell unit at the specified row and column.
187      */
188     API_EXPORT CellUnit *GetCellUnit(uint32_t row, uint32_t column);
189 
190     /**
191      * @brief Obtains string type data from cell unit.
192      */
GetCellUnitValueString(CellUnit * cellUnit,size_t * outSizeIncludingNull)193     API_EXPORT const char *GetCellUnitValueString(CellUnit *cellUnit, size_t *outSizeIncludingNull)
194     {
195         *outSizeIncludingNull = cellUnit->cell.stringOrBlobValue.size;
196         return static_cast<char *>(
197             OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size));
198     }
199 
200     /**
201      * @brief Obtains blob type data from cell unit.
202      */
GetCellUnitValueBlob(CellUnit * cellUnit,size_t * outSize)203     API_EXPORT const void *GetCellUnitValueBlob(CellUnit *cellUnit, size_t *outSize)
204     {
205         *outSize = cellUnit->cell.stringOrBlobValue.size;
206         return OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size);
207     }
208 
209     /**
210      * @brief Obtains the mHeader of the current result set.
211      */
GetHeader()212     API_EXPORT const void *GetHeader()
213     {
214         return mHeader;
215     }
216 
217     /**
218      * @brief Obtains size of the used byte in the block.
219      */
GetUsedBytes()220     API_EXPORT size_t GetUsedBytes()
221     {
222         return mHeader->unusedOffset;
223     }
224 
225     /**
226      * @brief Obtains the name of the current result set.
227      */
Name()228     API_EXPORT std::string Name()
229     {
230         return mName;
231     }
232 
233     /**
234      * @brief Obtains the size of the current result set.
235      */
Size()236     API_EXPORT size_t Size()
237     {
238         return mSize;
239     }
240 
241     /**
242      * @brief Obtains the row number of the current result set.
243      */
GetRowNum()244     API_EXPORT uint32_t GetRowNum()
245     {
246         return mHeader->rowNums;
247     }
248 
249     /**
250      * @brief Obtains the column number of the current result set.
251      */
GetColumnNum()252     API_EXPORT uint32_t GetColumnNum()
253     {
254         return mHeader->columnNums;
255     }
256 
257     /**
258      * @brief Write message to parcel.
259      */
260     API_EXPORT int WriteMessageParcel(MessageParcel &parcel);
261 
262     /**
263      * @brief Read message to parcel.
264      */
265     API_EXPORT static int ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block);
266 
267     /**
268      * @brief Write raw data in block.
269      */
270     API_EXPORT size_t SetRawData(const void *rawData, size_t size);
271 
272     /**
273      * @brief Obtains the fd of shared memory
274      */
GetFd()275     API_EXPORT int GetFd()
276     {
277         if (ashmem_ == nullptr) {
278             return -1;
279         }
280         return ashmem_->GetAshmemFd();
281     }
282 
283     /**
284      * @brief Obtains the start position of the current result set.
285      */
GetStartPos()286     API_EXPORT uint32_t GetStartPos()
287     {
288         return mHeader->startPos_;
289     }
290 
291     /**
292      * @brief Obtains the last position of the current result set.
293      */
GetLastPos()294     API_EXPORT uint32_t GetLastPos()
295     {
296         return mHeader->lastPos_;
297     }
298 
299     /**
300      * @brief Obtains the block position of the current result set.
301      */
GetBlockPos()302     API_EXPORT uint32_t GetBlockPos()
303     {
304         return mHeader->blockPos_;
305     }
306 
307     /**
308      * @brief Set the start position of the current result set.
309      */
SetStartPos(uint32_t startPos)310     API_EXPORT void SetStartPos(uint32_t startPos)
311     {
312         mHeader->startPos_ = startPos;
313     }
314 
315     /**
316      * @brief Set the last position of the current result set.
317      */
SetLastPos(uint32_t lastPos)318     API_EXPORT void SetLastPos(uint32_t lastPos)
319     {
320         mHeader->lastPos_ = lastPos;
321     }
322 
323     /**
324      * @brief Set the block position of the current result set.
325      */
SetBlockPos(uint32_t blockPos)326     API_EXPORT void SetBlockPos(uint32_t blockPos)
327     {
328         mHeader->blockPos_ = blockPos;
329     }
330 
331 private:
332     std::string mName;
333     sptr<Ashmem> ashmem_;
334     uint8_t *mData;
335     size_t mSize;
336     bool mReadOnly;
337     static const size_t ROW_NUM_IN_A_GROUP = 128;
338     static const uint32_t GROUP_NUM = 128;
339     /**
340     * Default setting for SQLITE_MAX_COLUMN is 2000.
341     * We can set it at compile time to as large as 32767
342     */
343     static const size_t COL_MAX_NUM = 32767;
344 
345     struct SharedBlockHeader {
346         /* Offset of the lowest unused byte in the block. */
347         uint32_t unusedOffset;
348         /* Row numbers of the row group block. */
349         uint32_t rowNums;
350         /* Column numbers of the row group block. */
351         uint32_t columnNums;
352         /* start position of the current block. */
353         uint32_t startPos_;
354         /* last position of the current block. */
355         uint32_t lastPos_;
356         /* current position of the current block. */
357         uint32_t blockPos_;
358         uint32_t groupOffset[GROUP_NUM];
359     };
360 
361     struct RowGroupHeader {
362         uint32_t rowOffsets[ROW_NUM_IN_A_GROUP];
363     };
364 
365     SharedBlockHeader *mHeader;
366 
367     /**
368      * Allocate a portion of the block. Returns the offset of the allocation.
369      * Returns 0 if there isn't enough space.
370      */
371     inline uint32_t Alloc(size_t size);
372 
373     inline uint32_t *AllocRowOffset();
374 
375     inline int PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type);
376 
377     static int CreateSharedBlock(const std::string &name, size_t size, sptr<Ashmem> ashmem,
378         SharedBlock *&outSharedBlock);
379 
380     inline void *OffsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
381         uint32_t safeOffset = offset;
382         if (safeOffset + bufferSize > mSize) {
383             return nullptr;
384         }
385         return mData + safeOffset;
386     }
387 };
388 } // namespace AppDataFwk
389 } // namespace OHOS
390 #endif
391