1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.appsearch.external.localstorage; 18 19 import android.app.appsearch.SearchSpec; 20 21 import com.google.android.icing.proto.IcingSearchEngineOptions; 22 23 /** 24 * An interface exposing the optional config flags in {@link IcingSearchEngineOptions} used to 25 * instantiate {@link com.google.android.icing.IcingSearchEngine}, as well as other additional 26 * config flags for IcingSearchEngine. 27 */ 28 public interface IcingOptionsConfig { 29 // Defaults from IcingSearchEngineOptions proto 30 int DEFAULT_MAX_TOKEN_LENGTH = 30; 31 32 int DEFAULT_INDEX_MERGE_SIZE = 1048576; // 1 MiB 33 34 boolean DEFAULT_DOCUMENT_STORE_NAMESPACE_ID_FINGERPRINT = false; 35 36 float DEFAULT_OPTIMIZE_REBUILD_INDEX_THRESHOLD = 0.9f; 37 38 /** 39 * The default compression level in IcingSearchEngineOptions proto matches the 40 * previously-hardcoded document compression level in Icing (which is 3). 41 */ 42 int DEFAULT_COMPRESSION_LEVEL = 3; 43 44 boolean DEFAULT_USE_PREMAPPING_WITH_FILE_BACKED_VECTOR = false; 45 46 boolean DEFAULT_USE_PERSISTENT_HASH_MAP = false; 47 48 int DEFAULT_MAX_PAGE_BYTES_LIMIT = Integer.MAX_VALUE; 49 50 /** 51 * The default threshold for integer index bucket split. 65536 is picked based on benchmark 52 * (Icing integer-index-storage_benchmark.cc). 53 * 54 * <ul> 55 * <li>There will be only 16 buckets when indexing 1M integers, which improves the performance 56 * of numeric search range query. 57 * <li>It also increases # of hits to read for numeric search exact query, but the overall 58 * query latency is still reasonable. 59 * </ul> 60 */ 61 int DEFAULT_INTEGER_INDEX_BUCKET_SPLIT_THRESHOLD = 65536; 62 63 boolean DEFAULT_LITE_INDEX_SORT_AT_INDEXING = true; 64 65 /** 66 * The default sort threshold for the lite index when sort at indexing is enabled. 8192 is 67 * picked based on Icing microbenchmarks (icing-search-engine_benchmarks.cc). 68 */ 69 int DEFAULT_LITE_INDEX_SORT_SIZE = 8192; // 8Kib 70 71 boolean DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX = false; 72 73 boolean DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS = false; 74 75 /** 76 * The maximum allowable token length. All tokens in excess of this size will be truncated to 77 * max_token_length before being indexed. 78 * 79 * <p>Clients may use this option to prevent unnecessary indexing of long tokens. Depending on 80 * the use case, indexing all of 'Supercalifragilisticexpialidocious' may be unnecessary - a 81 * user is unlikely to type that entire query. So only indexing the first n bytes may still 82 * provide the desired behavior without wasting resources. 83 */ getMaxTokenLength()84 int getMaxTokenLength(); 85 86 /** 87 * The size (measured in bytes) at which Icing's internal indices should be merged. Icing 88 * buffers changes together before merging them into a more compact format. When the buffer 89 * exceeds index_merge_size during a Put operation, the buffer is merged into the larger, more 90 * compact index. 91 * 92 * <p>This more compact index is more efficient to search over as the index grows larger and has 93 * smaller system health impact. 94 * 95 * <p>Setting a low index_merge_size increases the frequency of merges - increasing 96 * indexing-time latency and flash wear. Setting a high index_merge_size leads to larger 97 * resource usage and higher query latency. 98 */ getIndexMergeSize()99 int getIndexMergeSize(); 100 101 /** 102 * Whether to use namespace id or namespace name to build up fingerprint for 103 * document_key_mapper_ and corpus_mapper_ in document store. 104 */ getDocumentStoreNamespaceIdFingerprint()105 boolean getDocumentStoreNamespaceIdFingerprint(); 106 107 /** 108 * The threshold of the percentage of invalid documents at which to rebuild index during 109 * optimize. 110 * 111 * <p>We rebuild index if and only if |invalid_documents| / |all_documents| >= threshold. 112 * 113 * <p>Rebuilding the index could be faster than optimizing the index if we have removed most of 114 * the documents. Based on benchmarks, 85%~95% seems to be a good threshold for most cases. 115 */ getOptimizeRebuildIndexThreshold()116 float getOptimizeRebuildIndexThreshold(); 117 118 /** 119 * The level of gzip compression for documents in the Icing document store. 120 * 121 * <p>NO_COMPRESSION = 0, BEST_SPEED = 1, BEST_COMPRESSION = 9 122 */ getCompressionLevel()123 int getCompressionLevel(); 124 125 /** 126 * Whether to allow circular references between schema types for the schema definition. 127 * 128 * <p>Even when set to true, circular references are still not allowed in the following cases: 129 * 1. All edges of a cycle have index_nested_properties=true 2. One of the types in the cycle 130 * has a joinable property, or depends on a type with a joinable property. 131 */ getAllowCircularSchemaDefinitions()132 boolean getAllowCircularSchemaDefinitions(); 133 134 /** 135 * Flag for {@link com.google.android.icing.proto.SearchSpecProto}. 136 * 137 * <p>Whether to use the read-only implementation of IcingSearchEngine::Search. 138 * 139 * <p>The read-only version enables multiple queries to be performed concurrently as it only 140 * acquires the read lock at IcingSearchEngine's level. Finer-grained locks are implemented 141 * around code paths that write changes to Icing during Search. 142 */ getUseReadOnlySearch()143 boolean getUseReadOnlySearch(); 144 145 /** 146 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 147 * 148 * <p>Whether or not to pre-map the potential memory region used by the PersistentHashMap. This 149 * will avoid the need to re-map the mmapping used by PersistentHashMap whenever the underlying 150 * storage grows. 151 */ getUsePreMappingWithFileBackedVector()152 boolean getUsePreMappingWithFileBackedVector(); 153 154 /** 155 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 156 * 157 * <p>Whether or not to use the PersistentHashMap in the QualifiedIdTypeJoinableIndex. If false, 158 * we will use the old IcingDynamicTrie to store key value pairs. 159 */ getUsePersistentHashMap()160 boolean getUsePersistentHashMap(); 161 162 /** 163 * Flag for {@link com.google.android.icing.proto.ResultSpecProto}. 164 * 165 * <p>The maximum byte size to allow in a single page. This limit is only loosely binding. 166 * AppSearch will add results to the page until either 1) AppSearch has retrieved {@link 167 * SearchSpec#getResultCountPerPage()} results or 2) total size of the page exceeds this value. 168 * Therefore, AppSearch will always retrieve at least a single result, even if that result 169 * exceeds this limit. 170 */ getMaxPageBytesLimit()171 int getMaxPageBytesLimit(); 172 173 /** 174 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 175 * 176 * <p>Threshold for integer index bucket split. Integer index stores hits in several buckets, 177 * and splits if # of hits in a single bucket exceed the threshold. Splitting bucket accelerates 178 * numeric search exact query, but potentially downgrades the performance of range query. 179 * 180 * <p>This flag is for rolling out new threshold 65536. If identifying any issues, then change 181 * it back to 341 (the previous bucket split threshold, capacity of full max-sized posting 182 * list). 183 */ getIntegerIndexBucketSplitThreshold()184 int getIntegerIndexBucketSplitThreshold(); 185 186 /** 187 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 188 * 189 * <p>Whether Icing should sort and merge its lite index HitBuffer unsorted tail at indexing 190 * time. 191 * 192 * <p>If set to true, the HitBuffer will be sorted at indexing time after exceeding the sort 193 * threshold. If false, the HifBuffer will be sorted at querying time, before the first query 194 * after inserting new elements into the HitBuffer. 195 */ getLiteIndexSortAtIndexing()196 boolean getLiteIndexSortAtIndexing(); 197 198 /** 199 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 200 * 201 * <p>Size (in bytes) at which Icing's lite index should sort and merge the HitBuffer's unsorted 202 * tail into the sorted head for sorting at indexing time. Size specified here is unsorted tail 203 * section. 204 * 205 * <p>Setting a lower sort size reduces querying latency at the expense of indexing latency. 206 */ getLiteIndexSortSize()207 int getLiteIndexSortSize(); 208 209 /** 210 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 211 * 212 * <p>Whether to use the new qualified Id join index. 213 */ getUseNewQualifiedIdJoinIndex()214 boolean getUseNewQualifiedIdJoinIndex(); 215 216 /** 217 * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}. 218 * 219 * <p>Whether to build the metadata hits used for property existence check, which is required to 220 * support the hasProperty function in advanced query. 221 */ getBuildPropertyExistenceMetadataHits()222 boolean getBuildPropertyExistenceMetadataHits(); 223 } 224