1 // Copyright (C) 2019 Google LLC 2 // 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 #ifndef ICING_FILE_POSTING_LIST_POSTING_LIST_FREE_H_ 16 #define ICING_FILE_POSTING_LIST_POSTING_LIST_FREE_H_ 17 18 #include <cstdint> 19 #include <cstring> 20 21 #include "icing/text_classifier/lib3/utils/base/statusor.h" 22 #include "icing/absl_ports/canonical_errors.h" 23 #include "icing/file/posting_list/posting-list-common.h" 24 #include "icing/file/posting_list/posting-list-utils.h" 25 #include "icing/legacy/core/icing-string-util.h" 26 #include "icing/util/status-macros.h" 27 28 namespace icing { 29 namespace lib { 30 31 // A posting list in the index block's free list. 32 // 33 // We re-use the first sizeof(PostingListIndex) bytes of the posting list 34 // buffer to store a next index for chaining. 35 class PostingListFree { 36 public: 37 // Creates a PostingListFree that points to a buffer of size_in_bytes bytes. 38 // 'Preexisting' means that posting_list_buffer was previously modified by 39 // another instance of PostingListFree. 40 // 41 // Caller owns the posting_list_buffer and must not free it while using 42 // a PostingListFree. 43 // 44 // RETURNS: 45 // - A valid PostingListFree on success 46 // - INVALID_ARGUMENT if posting_list_utils::IsValidPostingListSize check 47 // fails 48 // - FAILED_PRECONDITION if posting_list_buffer is null 49 static libtextclassifier3::StatusOr<PostingListFree> CreateFromPreexistingPostingListFreeRegion(void * posting_list_buffer,uint32_t size_in_bytes,uint32_t data_type_bytes,uint32_t min_posting_list_size)50 CreateFromPreexistingPostingListFreeRegion(void* posting_list_buffer, 51 uint32_t size_in_bytes, 52 uint32_t data_type_bytes, 53 uint32_t min_posting_list_size) { 54 ICING_RETURN_ERROR_IF_NULL(posting_list_buffer); 55 if (!posting_list_utils::IsValidPostingListSize( 56 size_in_bytes, data_type_bytes, min_posting_list_size)) { 57 return absl_ports::InvalidArgumentError(IcingStringUtil::StringPrintf( 58 "Requested posting list size %d is invalid!", size_in_bytes)); 59 } 60 return PostingListFree(posting_list_buffer, size_in_bytes); 61 } 62 63 // Creates a PostingListFree that points to a buffer of size_in_bytes bytes 64 // and initializes the content of the buffer so that the returned 65 // PostingListFree is empty. 66 // 67 // Caller owns the posting_list_buffer buffer and must not free it while using 68 // a PostingListFree. 69 // 70 // RETURNS: 71 // - A valid PostingListFree on success 72 // - INVALID_ARGUMENT if posting_list_utils::IsValidPostingListSize check 73 // fails 74 // - FAILED_PRECONDITION if posting_list_buffer is null 75 static libtextclassifier3::StatusOr<PostingListFree> CreateFromUnitializedRegion(void * posting_list_buffer,uint32_t size_in_bytes,uint32_t data_type_bytes,uint32_t min_posting_list_size)76 CreateFromUnitializedRegion(void* posting_list_buffer, uint32_t size_in_bytes, 77 uint32_t data_type_bytes, 78 uint32_t min_posting_list_size) { 79 ICING_ASSIGN_OR_RETURN(PostingListFree posting_list_free, 80 CreateFromPreexistingPostingListFreeRegion( 81 posting_list_buffer, size_in_bytes, 82 data_type_bytes, min_posting_list_size)); 83 posting_list_free.Clear(); 84 return posting_list_free; 85 } 86 87 // Used to store/access the index of the next free posting list in this 88 // index block. get_next_posting_list_index()89 PostingListIndex get_next_posting_list_index() const { 90 PostingListIndex posting_list_index; 91 memcpy(&posting_list_index, posting_list_buffer_, 92 sizeof(posting_list_index)); 93 return posting_list_index; 94 } set_next_posting_list_index(PostingListIndex posting_list_index)95 void set_next_posting_list_index(PostingListIndex posting_list_index) { 96 memcpy(posting_list_buffer_, &posting_list_index, 97 sizeof(posting_list_index)); 98 } 99 100 private: PostingListFree(void * posting_list_buffer,uint32_t size_in_bytes)101 explicit PostingListFree(void* posting_list_buffer, uint32_t size_in_bytes) 102 : posting_list_buffer_(static_cast<uint8_t*>(posting_list_buffer)), 103 size_in_bytes_(size_in_bytes) {} 104 105 // Reset the current free posting list as unchained free posting list so that 106 // there's no next posting list index. This *must* be called if the 107 // posting_list_buffer_ region was never used for a previous instance of 108 // PostingListFree. Clear()109 void Clear() { set_next_posting_list_index(kInvalidPostingListIndex); } 110 111 // A byte array of size size_in_bytes_. The first sizeof(PostingListIndex) 112 // bytes which will store the next posting list index, the rest are unused and 113 // can be anything. 114 uint8_t* posting_list_buffer_; 115 [[maybe_unused]] uint32_t size_in_bytes_; 116 }; 117 118 } // namespace lib 119 } // namespace icing 120 121 #endif // ICING_FILE_POSTING_LIST_POSTING_LIST_FREE_H_ 122