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 #include <cstdint> 16 17 #include "icing/file/file-backed-vector.h" 18 #include "icing/proto/usage.pb.h" 19 #include "icing/store/document-id.h" 20 21 #ifndef ICING_STORE_USAGE_STORE_H_ 22 #define ICING_STORE_USAGE_STORE_H_ 23 24 namespace icing { 25 namespace lib { 26 27 // A storage class that maintains scores that are calculated based on usage 28 // reports. 29 class UsageStore { 30 public: 31 // Factory function to create a UsageStore instance. The base directory is 32 // used to persist usage scores. If a usage store was previously created with 33 // this directory, it will reload the files saved by the last instance. 34 // 35 // TODO(b/169594617): consider returning StatusOr<UsageStore> 36 // 37 // Returns: 38 // A UsageStore on success 39 // FAILED_PRECONDITION on any null pointer input 40 // INTERNAL_ERROR on I/O error 41 static libtextclassifier3::StatusOr<std::unique_ptr<UsageStore>> Create( 42 const Filesystem* filesystem, const std::string& base_dir); 43 44 // The scores here reflect the timestamps and usage types defined in 45 // usage.proto. 46 struct UsageScores { 47 // The latest timestamp in seconds reported with custom usage type 1. 48 uint32_t usage_type1_last_used_timestamp_s = 0; 49 50 // The latest timestamp in seconds reported with custom usage type 2. 51 uint32_t usage_type2_last_used_timestamp_s = 0; 52 53 // The latest timestamp in seconds reported with custom usage type 3. 54 uint32_t usage_type3_last_used_timestamp_s = 0; 55 56 // Count of reports with custom usage type 1 57 int usage_type1_count = 0; 58 59 // Count of reports with custom usage type 2 60 int usage_type2_count = 0; 61 62 // Count of reports with custom usage type 3 63 int usage_type3_count = 0; 64 65 bool operator==(const UsageScores& other) const { 66 return usage_type1_last_used_timestamp_s == 67 other.usage_type1_last_used_timestamp_s && 68 usage_type2_last_used_timestamp_s == 69 other.usage_type2_last_used_timestamp_s && 70 usage_type3_last_used_timestamp_s == 71 other.usage_type3_last_used_timestamp_s && 72 usage_type1_count == other.usage_type1_count && 73 usage_type2_count == other.usage_type2_count && 74 usage_type3_count == other.usage_type3_count; 75 } 76 }; 77 78 // Adds one usage report. The corresponding usage scores of the specified 79 // document will be updated. 80 // 81 // Note: changes are written to disk automatically, callers can also call 82 // PersistToDisk() to flush changes immediately. 83 // 84 // Returns: 85 // OK on success 86 // INVALID_ARGUMENT if document_id is invalid 87 // INTERNAL_ERROR on I/O errors. 88 libtextclassifier3::Status AddUsageReport(const UsageReport& report, 89 DocumentId document_id); 90 91 // Deletes the usage scores of a document. 92 // 93 // Note: changes are written to disk automatically, callers can also call 94 // PersistToDisk() to flush changes immediately. 95 // 96 // Returns: 97 // OK on success 98 // INVALID_ARGUMENT if document_id is invalid 99 // INTERNAL_ERROR on I/O errors 100 libtextclassifier3::Status DeleteUsageScores(DocumentId document_id); 101 102 // Gets the usage scores of a document. 103 // 104 // Returns: 105 // UsageScores on success 106 // INVALID_ARGUMENT if document_id is invalid 107 // INTERNAL_ERROR on I/O errors 108 // 109 // TODO(b/169433395): return a pointer instead of an object. 110 libtextclassifier3::StatusOr<UsageScores> GetUsageScores( 111 DocumentId document_id); 112 113 // Sets the usage scores of a document. 114 // 115 // Note: changes are written to disk automatically, callers can also call 116 // PersistToDisk() to flush changes immediately. 117 // 118 // Returns: 119 // OK on success 120 // INVALID_ARGUMENT if document_id is invalid 121 // INTERNAL_ERROR on I/O errors 122 libtextclassifier3::Status SetUsageScores(DocumentId document_id, 123 const UsageScores& usage_scores); 124 125 // Clones the usage scores from one document to another. 126 // 127 // Returns: 128 // OK on success 129 // INVALID_ARGUMENT if any of the document ids is invalid 130 // INTERNAL_ERROR on I/O errors 131 // 132 // TODO(b/169433395): We can remove this method once GetUsageScores() returns 133 // a pointer. 134 libtextclassifier3::Status CloneUsageScores(DocumentId from_document_id, 135 DocumentId to_document_id); 136 137 // Syncs data to disk. 138 // 139 // Returns: 140 // OK on success 141 // INTERNAL on I/O error 142 libtextclassifier3::Status PersistToDisk(); 143 144 // Updates checksum of the usage scores and returns it. 145 // 146 // Returns: 147 // A Crc32 on success 148 // INTERNAL_ERROR if the internal state is inconsistent 149 libtextclassifier3::StatusOr<Crc32> ComputeChecksum(); 150 151 // Returns the file size of the all the elements held in the UsageStore. File 152 // size is in bytes. This excludes the size of any internal metadata, e.g. any 153 // internal headers. 154 // 155 // Returns: 156 // File size on success 157 // INTERNAL_ERROR on IO error 158 libtextclassifier3::StatusOr<int64_t> GetElementsFileSize() const; 159 160 // Calculates and returns the disk usage in bytes. Rounds up to the nearest 161 // block size. 162 // 163 // Returns: 164 // Disk usage on success 165 // INTERNAL_ERROR on IO error 166 libtextclassifier3::StatusOr<int64_t> GetDiskUsage() const; 167 168 // Resizes the storage so that only the usage scores of and before 169 // last_document_id are stored. 170 // 171 // Returns: 172 // OK on success 173 // OUT_OF_RANGE_ERROR if num_documents is negative 174 libtextclassifier3::Status TruncateTo(DocumentId num_documents); 175 176 // Deletes all usage data and re-initialize the storage. 177 // 178 // Returns: 179 // OK on success 180 // INTERNAL_ERROR on I/O error 181 libtextclassifier3::Status Reset(); 182 num_elements()183 int32_t num_elements() const { return usage_score_cache_->num_elements(); } 184 185 private: UsageStore(std::unique_ptr<FileBackedVector<UsageScores>> document_id_to_scores_mapper,const Filesystem & filesystem,std::string base_dir)186 explicit UsageStore(std::unique_ptr<FileBackedVector<UsageScores>> 187 document_id_to_scores_mapper, 188 const Filesystem& filesystem, std::string base_dir) 189 : filesystem_(filesystem), 190 base_dir_(std::move(base_dir)), 191 usage_score_cache_(std::move(document_id_to_scores_mapper)) {} 192 193 const Filesystem& filesystem_; 194 195 // Base directory where the files are located. 196 const std::string base_dir_; 197 198 // Used to store the usage scores of documents. 199 std::unique_ptr<FileBackedVector<UsageScores>> usage_score_cache_; 200 }; 201 202 } // namespace lib 203 } // namespace icing 204 205 #endif // ICING_STORE_USAGE_STORE_H_ 206