1 // Copyright (C) 2022 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_RESULT_RESULT_STATE_V2_H_ 16 #define ICING_RESULT_RESULT_STATE_V2_H_ 17 18 #include <atomic> 19 #include <cstdint> 20 #include <memory> 21 #include <unordered_map> 22 #include <vector> 23 24 #include "icing/absl_ports/mutex.h" 25 #include "icing/absl_ports/thread_annotations.h" 26 #include "icing/proto/search.pb.h" 27 #include "icing/result/result-adjustment-info.h" 28 #include "icing/scoring/scored-document-hits-ranker.h" 29 #include "icing/store/document-store.h" 30 31 namespace icing { 32 namespace lib { 33 34 // Used to hold information needed across multiple pagination requests of the 35 // same query. Stored in ResultStateManager. 36 class ResultStateV2 { 37 public: 38 explicit ResultStateV2( 39 std::unique_ptr<ScoredDocumentHitsRanker> scored_document_hits_ranker_in, 40 std::unique_ptr<ResultAdjustmentInfo> parent_adjustment_info, 41 std::unique_ptr<ResultAdjustmentInfo> child_adjustment_info, 42 const ResultSpecProto& result_spec, const DocumentStore& document_store); 43 44 ~ResultStateV2(); 45 46 // Register num_total_hits_ and add current scored_document_hits_ranker.size() 47 // to it. When re-registering, it will subtract 48 // scored_document_hits_ranker.size() from the original counter. 49 void RegisterNumTotalHits(std::atomic<int>* num_total_hits) 50 ICING_EXCLUSIVE_LOCKS_REQUIRED(mutex); 51 52 // Increment the global counter num_total_hits_ by increment_by, if 53 // num_total_hits_ has been registered (is not nullptr). 54 // Note that providing a negative value for increment_by is a valid usage, 55 // which will actually decrement num_total_hits_. 56 // 57 // It has to be called when we change scored_document_hits_ranker. 58 void IncrementNumTotalHits(int increment_by) 59 ICING_EXCLUSIVE_LOCKS_REQUIRED(mutex); 60 61 // Returns a nullable pointer to parent adjustment info. parent_adjustment_info()62 ResultAdjustmentInfo* parent_adjustment_info() 63 ICING_EXCLUSIVE_LOCKS_REQUIRED(mutex) { 64 return parent_adjustment_info_.get(); 65 } 66 67 // Returns a nullable pointer to parent adjustment info. parent_adjustment_info()68 const ResultAdjustmentInfo* parent_adjustment_info() const 69 ICING_SHARED_LOCKS_REQUIRED(mutex) { 70 return parent_adjustment_info_.get(); 71 } 72 73 // Returns a nullable pointer to child adjustment info. child_adjustment_info()74 ResultAdjustmentInfo* child_adjustment_info() 75 ICING_EXCLUSIVE_LOCKS_REQUIRED(mutex) { 76 return child_adjustment_info_.get(); 77 } 78 79 // Returns a nullable pointer to child adjustment info. child_adjustment_info()80 const ResultAdjustmentInfo* child_adjustment_info() const 81 ICING_SHARED_LOCKS_REQUIRED(mutex) { 82 return child_adjustment_info_.get(); 83 } 84 entry_id_group_id_map()85 const std::unordered_map<int32_t, int>& entry_id_group_id_map() const 86 ICING_SHARED_LOCKS_REQUIRED(mutex) { 87 return entry_id_group_id_map_; 88 } 89 num_per_page()90 int32_t num_per_page() const ICING_SHARED_LOCKS_REQUIRED(mutex) { 91 return num_per_page_; 92 } 93 num_total_bytes_per_page_threshold()94 int32_t num_total_bytes_per_page_threshold() const 95 ICING_SHARED_LOCKS_REQUIRED(mutex) { 96 return num_total_bytes_per_page_threshold_; 97 } 98 max_joined_children_per_parent_to_return()99 int32_t max_joined_children_per_parent_to_return() const 100 ICING_SHARED_LOCKS_REQUIRED(mutex) { 101 return max_joined_children_per_parent_to_return_; 102 } 103 result_group_type()104 ResultSpecProto::ResultGroupingType result_group_type() 105 ICING_SHARED_LOCKS_REQUIRED(mutex) { 106 return result_group_type_; 107 } 108 109 absl_ports::shared_mutex mutex; 110 111 // When evaluating the next top K hits from scored_document_hits_ranker, some 112 // of them may be filtered out by group_result_limits and won't return to the 113 // client, so they shouldn't be counted into num_returned. Also the logic of 114 // group result limiting depends on retrieval, so it is impossible for 115 // ResultState itself to correctly modify these fields. Thus, we make them 116 // public, so users of this class can modify them directly. 117 118 // The scored document hits ranker. 119 std::unique_ptr<ScoredDocumentHitsRanker> scored_document_hits_ranker 120 ICING_GUARDED_BY(mutex); 121 122 // The count of remaining results to return for a group where group id is the 123 // index. 124 std::vector<int> group_result_limits ICING_GUARDED_BY(mutex); 125 126 // Number of results that have already been returned. 127 int num_returned ICING_GUARDED_BY(mutex); 128 129 private: 130 // Adjustment information for parent documents, including snippet and 131 // projection. Can be nullptr if there is no adjustment info for parent 132 // documents. 133 std::unique_ptr<ResultAdjustmentInfo> parent_adjustment_info_ 134 ICING_GUARDED_BY(mutex); 135 136 // Adjustment information for child documents, including snippet and 137 // projection. This is only used for join query. Can be nullptr if there is no 138 // adjustment info for child documents. 139 std::unique_ptr<ResultAdjustmentInfo> child_adjustment_info_ 140 ICING_GUARDED_BY(mutex); 141 142 // A map between result grouping entry id and the id of the group that it 143 // appears in. 144 std::unordered_map<int32_t, int> entry_id_group_id_map_ 145 ICING_GUARDED_BY(mutex); 146 147 // Number of results to return in each page. 148 int32_t num_per_page_ ICING_GUARDED_BY(mutex); 149 150 // The threshold of total bytes of all documents to cutoff, in order to limit 151 // # of bytes in a single page. 152 // Note that it doesn't guarantee the result # of bytes will be smaller, equal 153 // to, or larger than the threshold. Instead, it is just a threshold to 154 // cutoff, and only guarantees total bytes of search results won't exceed the 155 // threshold too much. 156 int32_t num_total_bytes_per_page_threshold_ ICING_GUARDED_BY(mutex); 157 158 // Max # of joined child documents to be attached in the result for each 159 // parent document. 160 int32_t max_joined_children_per_parent_to_return_ ICING_GUARDED_BY(mutex); 161 162 // Pointer to a global counter to sum up the size of scored_document_hits in 163 // all ResultStates. 164 // Does not own. 165 std::atomic<int>* num_total_hits_ ICING_GUARDED_BY(mutex); 166 167 // Value that the search results will get grouped by. 168 ResultSpecProto::ResultGroupingType result_group_type_ 169 ICING_GUARDED_BY(mutex); 170 }; 171 172 } // namespace lib 173 } // namespace icing 174 175 #endif // ICING_RESULT_RESULT_STATE_V2_H_ 176