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