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 }; 59 60 /** 61 * @brief SharedBlock error types. 62 */ 63 enum { 64 /** Indicates that the operation on SHARED BLOCK was successful.*/ 65 SHARED_BLOCK_OK = 0, 66 /** Indicates that the result returned by the shared block operation is a bad value.*/ 67 SHARED_BLOCK_BAD_VALUE = 1, 68 /** Indicates the current shared block space is not enough.*/ 69 SHARED_BLOCK_NO_MEMORY = 2, 70 /** Indicates that the current operation on SHARED BLOCK is invalid.*/ 71 SHARED_BLOCK_INVALID_OPERATION = 3, 72 /** Indicates that an ashmem error occurred in the operation of shared memory.*/ 73 SHARED_BLOCK_ASHMEM_ERROR = 4, 74 /** Indicates that the set port error occurred in the operation of shared memory.*/ 75 SHARED_BLOCK_SET_PORT_ERROR = 5, 76 }; 77 78 /** 79 * Cell Unit 80 * */ 81 struct CellUnit { 82 int32_t type; 83 union { 84 double doubleValue; 85 int64_t longValue; 86 struct { 87 uint32_t offset; 88 uint32_t size; 89 } stringOrBlobValue; 90 } cell; 91 } __attribute((packed)); 92 93 /** 94 * @brief Constructor. 95 */ 96 API_EXPORT SharedBlock(const std::string &name, sptr<Ashmem> ashmem, size_t size, bool readOnly); 97 98 /** 99 * @brief Destructor. 100 */ 101 API_EXPORT ~SharedBlock(); 102 103 /** 104 * @brief Init current shared block. 105 */ 106 API_EXPORT bool Init(); 107 108 /** 109 * @brief Create a shared block. 110 */ 111 API_EXPORT static int Create(const std::string &name, size_t size, SharedBlock *&outSharedBlock); 112 113 /** 114 * @brief Clear current shared block. 115 */ 116 API_EXPORT int Clear(); 117 118 /** 119 * @brief Set a shared block column. 120 */ 121 API_EXPORT int SetColumnNum(uint32_t numColumns); 122 123 /** 124 * @brief Allocate a row unit and its directory. 125 */ 126 API_EXPORT int AllocRow(); 127 128 /** 129 * @brief Release the value of the last row. 130 */ 131 API_EXPORT int FreeLastRow(); 132 133 /** 134 * @brief Put blob data to the shared block. 135 */ 136 API_EXPORT int PutBlob(uint32_t row, uint32_t column, const void *value, size_t Size); 137 138 /** 139 * @brief Put string data to the shared block. 140 */ 141 API_EXPORT int PutString(uint32_t row, uint32_t column, const char *value, size_t sizeIncludingNull); 142 143 /** 144 * @brief Put long data to the shared block. 145 */ 146 API_EXPORT int PutLong(uint32_t row, uint32_t column, int64_t value); 147 148 /** 149 * @brief Put Double data to the shared block. 150 */ 151 API_EXPORT int PutDouble(uint32_t row, uint32_t column, double value); 152 153 /** 154 * @brief Put Asset data to the shared block. 155 */ 156 API_EXPORT int PutAsset(uint32_t row, uint32_t column, const void *value, size_t size); 157 158 /** 159 * @brief Put Assets data to the shared block. 160 */ 161 API_EXPORT int PutAssets(uint32_t row, uint32_t column, const void *value, size_t size); 162 163 /** 164 * @brief Put Null data to the shared block. 165 */ 166 API_EXPORT int PutNull(uint32_t row, uint32_t column); 167 168 /** 169 * @brief Obtains the cell unit at the specified row and column. 170 */ 171 API_EXPORT CellUnit *GetCellUnit(uint32_t row, uint32_t column); 172 173 /** 174 * @brief Obtains string type data from cell unit. 175 */ GetCellUnitValueString(CellUnit * cellUnit,size_t * outSizeIncludingNull)176 API_EXPORT const char *GetCellUnitValueString(CellUnit *cellUnit, size_t *outSizeIncludingNull) 177 { 178 *outSizeIncludingNull = cellUnit->cell.stringOrBlobValue.size; 179 return static_cast<char *>( 180 OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size)); 181 } 182 183 /** 184 * @brief Obtains blob type data from cell unit. 185 */ GetCellUnitValueBlob(CellUnit * cellUnit,size_t * outSize)186 API_EXPORT const void *GetCellUnitValueBlob(CellUnit *cellUnit, size_t *outSize) 187 { 188 *outSize = cellUnit->cell.stringOrBlobValue.size; 189 return OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size); 190 } 191 192 /** 193 * @brief Obtains the mHeader of the current result set. 194 */ GetHeader()195 API_EXPORT const void *GetHeader() 196 { 197 return mHeader; 198 } 199 200 /** 201 * @brief Obtains size of the used byte in the block. 202 */ GetUsedBytes()203 API_EXPORT size_t GetUsedBytes() 204 { 205 return mHeader->unusedOffset; 206 } 207 208 /** 209 * @brief Obtains the name of the current result set. 210 */ Name()211 API_EXPORT std::string Name() 212 { 213 return mName; 214 } 215 216 /** 217 * @brief Obtains the size of the current result set. 218 */ Size()219 API_EXPORT size_t Size() 220 { 221 return mSize; 222 } 223 224 /** 225 * @brief Obtains the row number of the current result set. 226 */ GetRowNum()227 API_EXPORT uint32_t GetRowNum() 228 { 229 return mHeader->rowNums; 230 } 231 232 /** 233 * @brief Obtains the column number of the current result set. 234 */ GetColumnNum()235 API_EXPORT uint32_t GetColumnNum() 236 { 237 return mHeader->columnNums; 238 } 239 240 /** 241 * @brief Write message to parcel. 242 */ 243 API_EXPORT int WriteMessageParcel(MessageParcel &parcel); 244 245 /** 246 * @brief Read message to parcel. 247 */ 248 API_EXPORT static int ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block); 249 250 /** 251 * @brief Write raw data in block. 252 */ 253 API_EXPORT size_t SetRawData(const void *rawData, size_t size); 254 255 /** 256 * @brief Obtains the fd of shared memory 257 */ GetFd()258 API_EXPORT int GetFd() 259 { 260 if (ashmem_ == nullptr) { 261 return -1; 262 } 263 return ashmem_->GetAshmemFd(); 264 } 265 266 /** 267 * @brief Obtains the start position of the current result set. 268 */ GetStartPos()269 API_EXPORT uint32_t GetStartPos() 270 { 271 return mHeader->startPos_; 272 } 273 274 /** 275 * @brief Obtains the last position of the current result set. 276 */ GetLastPos()277 API_EXPORT uint32_t GetLastPos() 278 { 279 return mHeader->lastPos_; 280 } 281 282 /** 283 * @brief Obtains the block position of the current result set. 284 */ GetBlockPos()285 API_EXPORT uint32_t GetBlockPos() 286 { 287 return mHeader->blockPos_; 288 } 289 290 /** 291 * @brief Set the start position of the current result set. 292 */ SetStartPos(uint32_t startPos)293 API_EXPORT void SetStartPos(uint32_t startPos) 294 { 295 mHeader->startPos_ = startPos; 296 } 297 298 /** 299 * @brief Set the last position of the current result set. 300 */ SetLastPos(uint32_t lastPos)301 API_EXPORT void SetLastPos(uint32_t lastPos) 302 { 303 mHeader->lastPos_ = lastPos; 304 } 305 306 /** 307 * @brief Set the block position of the current result set. 308 */ SetBlockPos(uint32_t blockPos)309 API_EXPORT void SetBlockPos(uint32_t blockPos) 310 { 311 mHeader->blockPos_ = blockPos; 312 } 313 314 private: 315 std::string mName; 316 sptr<Ashmem> ashmem_; 317 uint8_t *mData; 318 size_t mSize; 319 bool mReadOnly; 320 static const size_t ROW_NUM_IN_A_GROUP = 128; 321 static const uint32_t GROUP_NUM = 128; 322 /** 323 * Default setting for SQLITE_MAX_COLUMN is 2000. 324 * We can set it at compile time to as large as 32767 325 */ 326 static const size_t COL_MAX_NUM = 32767; 327 328 struct SharedBlockHeader { 329 /* Offset of the lowest unused byte in the block. */ 330 uint32_t unusedOffset; 331 /* Row numbers of the row group block. */ 332 uint32_t rowNums; 333 /* Column numbers of the row group block. */ 334 uint32_t columnNums; 335 /* start position of the current block. */ 336 uint32_t startPos_; 337 /* last position of the current block. */ 338 uint32_t lastPos_; 339 /* current position of the current block. */ 340 uint32_t blockPos_; 341 uint32_t groupOffset[GROUP_NUM]; 342 }; 343 344 struct RowGroupHeader { 345 uint32_t rowOffsets[ROW_NUM_IN_A_GROUP]; 346 }; 347 348 SharedBlockHeader *mHeader; 349 350 /** 351 * Allocate a portion of the block. Returns the offset of the allocation. 352 * Returns 0 if there isn't enough space. 353 */ 354 inline uint32_t Alloc(size_t size); 355 356 inline uint32_t *AllocRowOffset(); 357 358 inline int PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type); 359 360 static int CreateSharedBlock(const std::string &name, size_t size, sptr<Ashmem> ashmem, 361 SharedBlock *&outSharedBlock); 362 363 inline void *OffsetToPtr(uint32_t offset, uint32_t bufferSize = 0) { 364 if (offset + bufferSize > mSize) { 365 return nullptr; 366 } 367 return mData + offset; 368 } 369 }; 370 } // namespace AppDataFwk 371 } // namespace OHOS 372 #endif 373