Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: components/safe_browsing_db/v4_store.cc

Issue 2409793002: Add detailed UMA metrics for v4_store, broken down by storeid. (Closed)
Patch Set: Mark old histograms as obsolete instead of deleting them Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/base64.h" 5 #include "base/base64.h"
6 #include "base/bind.h" 6 #include "base/bind.h"
7 #include "base/files/file_util.h" 7 #include "base/files/file_util.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/metrics/sparse_histogram.h" 10 #include "base/metrics/sparse_histogram.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "components/safe_browsing_db/v4_rice.h" 13 #include "components/safe_browsing_db/v4_rice.h"
14 #include "components/safe_browsing_db/v4_store.h" 14 #include "components/safe_browsing_db/v4_store.h"
15 #include "components/safe_browsing_db/v4_store.pb.h" 15 #include "components/safe_browsing_db/v4_store.pb.h"
16 #include "crypto/secure_hash.h" 16 #include "crypto/secure_hash.h"
17 #include "crypto/sha2.h" 17 #include "crypto/sha2.h"
18 18
19 using base::TimeTicks; 19 using base::TimeTicks;
20 20
21 namespace safe_browsing { 21 namespace safe_browsing {
22 22
23 namespace { 23 namespace {
24 24
25 // UMA related strings.
26 // Part 1: Represent the overall operation being performed.
27 const char kProcessFullUpdate[] = "SafeBrowsing.V4ProcessFullUpdate";
28 const char kProcessPartialUpdate[] = "SafeBrowsing.V4ProcessPartialUpdate";
29 const char kReadFromDisk[] = "SafeBrowsing.V4ReadFromDisk";
30 // Part 2: Represent the sub-operation being performed as part of the larger
31 // operation from part 1.
32 const char kApplyUpdate[] = ".ApplyUpdate";
33 const char kDecodeAdditions[] = ".DecodeAdditions";
34 const char kDecodeRemovals[] = ".DecodeRemovals";
35 const char kMergeUpdate[] = ".MergeUpdate";
36 // Part 3: Represent the unit of value being measured and logged.
37 const char kResult[] = ".Result";
38 const char kTime[] = ".Time";
39 // UMA metric names for this file are generated by appending one value each,
40 // in order, from parts 1, 2, and 3.
Nathan Parker 2016/10/14 20:48:32 nit: You're missing part 2.5, which is the store n
vakh (use Gerrit instead) 2016/10/15 00:09:04 Done.
41
25 const uint32_t kFileMagic = 0x600D71FE; 42 const uint32_t kFileMagic = 0x600D71FE;
26
27 const uint32_t kFileVersion = 9; 43 const uint32_t kFileVersion = 9;
28 44
29 std::string GetUmaSuffixForStore(const base::FilePath& file_path) { 45 std::string GetUmaSuffixForStore(const base::FilePath& file_path) {
30 return base::StringPrintf( 46 return base::StringPrintf(
31 ".%" PRIsFP, file_path.BaseName().RemoveExtension().value().c_str()); 47 ".%" PRIsFP, file_path.BaseName().RemoveExtension().value().c_str());
32 } 48 }
33 49
34 void RecordTimeWithAndWithoutStore(const std::string& metric, 50 void RecordTimeWithAndWithoutSuffix(const std::string& metric,
35 base::TimeDelta time, 51 base::TimeDelta time,
36 const base::FilePath& file_path) { 52 const base::FilePath& file_path) {
37 // The histograms below are a modified expansion of the 53 // The histograms below are a modified expansion of the
38 // UMA_HISTOGRAM_LONG_TIMES macro adapted to allow for a dynamically suffixed 54 // UMA_HISTOGRAM_LONG_TIMES macro adapted to allow for a dynamically suffixed
39 // histogram name. 55 // histogram name.
40 // Note: The factory creates and owns the histogram. 56 // Note: The factory creates and owns the histogram.
41 const int kBucketCount = 100; 57 const int kBucketCount = 100;
42 base::HistogramBase* histogram = base::Histogram::FactoryTimeGet( 58 base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
43 metric, base::TimeDelta::FromMilliseconds(1), 59 metric + kTime, base::TimeDelta::FromMilliseconds(1),
44 base::TimeDelta::FromMinutes(1), kBucketCount, 60 base::TimeDelta::FromMinutes(1), kBucketCount,
45 base::HistogramBase::kUmaTargetedHistogramFlag); 61 base::HistogramBase::kUmaTargetedHistogramFlag);
46 if (histogram) { 62 if (histogram) {
47 histogram->AddTime(time); 63 histogram->AddTime(time);
48 } 64 }
49 65
50 std::string suffix = GetUmaSuffixForStore(file_path); 66 std::string suffix = GetUmaSuffixForStore(file_path);
51 base::HistogramBase* histogram_suffix = base::Histogram::FactoryTimeGet( 67 base::HistogramBase* histogram_suffix = base::Histogram::FactoryTimeGet(
52 metric + suffix, base::TimeDelta::FromMilliseconds(1), 68 metric + suffix + kTime, base::TimeDelta::FromMilliseconds(1),
53 base::TimeDelta::FromMinutes(1), kBucketCount, 69 base::TimeDelta::FromMinutes(1), kBucketCount,
54 base::HistogramBase::kUmaTargetedHistogramFlag); 70 base::HistogramBase::kUmaTargetedHistogramFlag);
55 if (histogram_suffix) { 71 if (histogram_suffix) {
56 histogram_suffix->AddTime(time); 72 histogram_suffix->AddTime(time);
57 } 73 }
58 } 74 }
59 75
76 void RecordEnumWithAndWithoutSuffix(const std::string& metric,
77 int32_t value,
78 int32_t maximum,
79 const base::FilePath& file_path) {
80 // The histograms below are an expansion of the UMA_HISTOGRAM_ENUMERATION
81 // macro adapted to allow for a dynamically suffixed histogram name.
82 // Note: The factory creates and owns the histogram.
83 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
84 metric + kResult, 1, maximum, maximum + 1,
85 base::HistogramBase::kUmaTargetedHistogramFlag);
86 if (histogram) {
87 histogram->Add(value);
88 }
89
90 std::string suffix = GetUmaSuffixForStore(file_path);
91 base::HistogramBase* histogram_suffix = base::LinearHistogram::FactoryGet(
92 metric + suffix + kResult, 1, maximum, maximum + 1,
93 base::HistogramBase::kUmaTargetedHistogramFlag);
94 if (histogram_suffix) {
95 histogram_suffix->Add(value);
96 }
97 }
98
60 void RecordAddUnlumpedHashesTime(base::TimeDelta time) { 99 void RecordAddUnlumpedHashesTime(base::TimeDelta time) {
61 UMA_HISTOGRAM_LONG_TIMES("SafeBrowsing.V4AddUnlumpedHashesTime", time); 100 UMA_HISTOGRAM_LONG_TIMES("SafeBrowsing.V4AddUnlumpedHashes.Time", time);
62 } 101 }
63 102
64 void RecordApplyUpdateResult(ApplyUpdateResult result) { 103 void RecordApplyUpdateResult(const std::string& base_metric,
65 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4ApplyUpdateResult", result, 104 ApplyUpdateResult result,
66 APPLY_UPDATE_RESULT_MAX); 105 const base::FilePath& file_path) {
106 RecordEnumWithAndWithoutSuffix(base_metric + kApplyUpdate, result,
107 APPLY_UPDATE_RESULT_MAX, file_path);
67 } 108 }
68 109
69 void RecordApplyUpdateResultWhenReadingFromDisk(ApplyUpdateResult result) { 110 void RecordApplyUpdateTime(const std::string& base_metric,
70 UMA_HISTOGRAM_ENUMERATION( 111 base::TimeDelta time,
71 "SafeBrowsing.V4ApplyUpdateResultWhenReadingFromDisk", result, 112 const base::FilePath& file_path) {
72 APPLY_UPDATE_RESULT_MAX); 113 RecordTimeWithAndWithoutSuffix(base_metric + kApplyUpdate, time, file_path);
73 } 114 }
74 115
75 void RecordDecodeAdditionsResult(V4DecodeResult result) { 116 void RecordDecodeAdditionsResult(const std::string& base_metric,
76 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeAdditionsResult", result, 117 V4DecodeResult result,
77 DECODE_RESULT_MAX); 118 const base::FilePath& file_path) {
119 RecordEnumWithAndWithoutSuffix(base_metric + kDecodeAdditions, result,
120 DECODE_RESULT_MAX, file_path);
78 } 121 }
79 122
80 void RecordDecodeAdditionsTime(base::TimeDelta time, 123 void RecordDecodeAdditionsTime(const std::string& base_metric,
124 base::TimeDelta time,
81 const base::FilePath& file_path) { 125 const base::FilePath& file_path) {
82 RecordTimeWithAndWithoutStore("SafeBrowsing.V4DecodeAdditionsTime", time, 126 RecordTimeWithAndWithoutSuffix(base_metric + kDecodeAdditions, time,
83 file_path); 127 file_path);
84 } 128 }
85 129
86 void RecordDecodeRemovalsResult(V4DecodeResult result) { 130 void RecordDecodeRemovalsResult(const std::string& base_metric,
87 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeRemovalsResult", result, 131 V4DecodeResult result,
88 DECODE_RESULT_MAX); 132 const base::FilePath& file_path) {
133 RecordEnumWithAndWithoutSuffix(base_metric + kDecodeRemovals, result,
134 DECODE_RESULT_MAX, file_path);
89 } 135 }
90 136
91 void RecordDecodeRemovalsTime(base::TimeDelta time, 137 void RecordDecodeRemovalsTime(const std::string& base_metric,
138 base::TimeDelta time,
92 const base::FilePath& file_path) { 139 const base::FilePath& file_path) {
93 RecordTimeWithAndWithoutStore("SafeBrowsing.V4DecodeRemovalsTime", time, 140 RecordTimeWithAndWithoutSuffix(base_metric + kDecodeRemovals, time,
94 file_path); 141 file_path);
95 } 142 }
96 143
97 void RecordMergeUpdateTime(base::TimeDelta time, 144 void RecordMergeUpdateTime(const std::string& base_metric,
145 base::TimeDelta time,
98 const base::FilePath& file_path) { 146 const base::FilePath& file_path) {
99 RecordTimeWithAndWithoutStore("SafeBrowsing.V4MergeUpdateTime", time, 147 RecordTimeWithAndWithoutSuffix(base_metric + kMergeUpdate, time, file_path);
100 file_path);
101 }
102
103 void RecordProcessFullUpdateTime(base::TimeDelta time,
104 const base::FilePath& file_path) {
105 RecordTimeWithAndWithoutStore("SafeBrowsing.V4ProcessFullUpdateTime", time,
106 file_path);
107 }
108
109 void RecordProcessPartialUpdateTime(base::TimeDelta time,
110 const base::FilePath& file_path) {
111 RecordTimeWithAndWithoutStore("SafeBrowsing.V4ProcessPartialUpdateTime", time,
112 file_path);
113 }
114
115 void RecordReadFromDiskTime(base::TimeDelta time,
116 const base::FilePath& file_path) {
117 RecordTimeWithAndWithoutStore("SafeBrowsing.V4ReadFromDiskTime", time,
118 file_path);
119 } 148 }
120 149
121 void RecordStoreReadResult(StoreReadResult result) { 150 void RecordStoreReadResult(StoreReadResult result) {
122 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreReadResult", result, 151 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreRead.Result", result,
123 STORE_READ_RESULT_MAX); 152 STORE_READ_RESULT_MAX);
124 } 153 }
125 154
126 void RecordStoreWriteResult(StoreWriteResult result) { 155 void RecordStoreWriteResult(StoreWriteResult result) {
127 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreWriteResult", result, 156 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreWrite.Result", result,
128 STORE_WRITE_RESULT_MAX); 157 STORE_WRITE_RESULT_MAX);
129 } 158 }
130 159
131 // Returns the name of the temporary file used to buffer data for 160 // Returns the name of the temporary file used to buffer data for
132 // |filename|. Exported for unit tests. 161 // |filename|. Exported for unit tests.
133 const base::FilePath TemporaryFileForFilename(const base::FilePath& filename) { 162 const base::FilePath TemporaryFileForFilename(const base::FilePath& filename) {
134 return base::FilePath(filename.value() + FILE_PATH_LITERAL("_new")); 163 return base::FilePath(filename.value() + FILE_PATH_LITERAL("_new"));
135 } 164 }
136 165
137 } // namespace 166 } // namespace
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 store_path_.value().c_str(), state_base64.c_str()); 204 store_path_.value().c_str(), state_base64.c_str());
176 } 205 }
177 206
178 void V4Store::Reset() { 207 void V4Store::Reset() {
179 expected_checksum_.clear(); 208 expected_checksum_.clear();
180 hash_prefix_map_.clear(); 209 hash_prefix_map_.clear();
181 state_ = ""; 210 state_ = "";
182 } 211 }
183 212
184 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk( 213 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk(
214 const std::string& metric,
185 const HashPrefixMap& hash_prefix_map_old, 215 const HashPrefixMap& hash_prefix_map_old,
186 std::unique_ptr<ListUpdateResponse> response) { 216 std::unique_ptr<ListUpdateResponse> response) {
187 DCHECK(response->has_response_type()); 217 DCHECK(response->has_response_type());
188 DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type()); 218 DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type());
189 219
190 TimeTicks before = TimeTicks::Now(); 220 ApplyUpdateResult result =
191 ApplyUpdateResult result = ProcessUpdate(hash_prefix_map_old, response); 221 ProcessUpdate(metric, hash_prefix_map_old, response);
192 if (result == APPLY_UPDATE_SUCCESS) {
193 RecordProcessPartialUpdateTime(TimeTicks::Now() - before, store_path_);
194 // TODO(vakh): Create a ListUpdateResponse containing RICE encoded
195 // hash prefixes and response_type as FULL_UPDATE, and write that to disk.
196 }
197 return result; 222 return result;
198 } 223 }
199 224
200 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk( 225 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk(
226 const std::string& metric,
201 std::unique_ptr<ListUpdateResponse> response) { 227 std::unique_ptr<ListUpdateResponse> response) {
202 TimeTicks before = TimeTicks::Now(); 228 ApplyUpdateResult result = ProcessFullUpdate(metric, response);
203 ApplyUpdateResult result = ProcessFullUpdate(response);
204 if (result == APPLY_UPDATE_SUCCESS) { 229 if (result == APPLY_UPDATE_SUCCESS) {
205 RecordProcessFullUpdateTime(TimeTicks::Now() - before, store_path_);
206 RecordStoreWriteResult(WriteToDisk(std::move(response))); 230 RecordStoreWriteResult(WriteToDisk(std::move(response)));
207 } 231 }
208 return result; 232 return result;
209 } 233 }
210 234
211 ApplyUpdateResult V4Store::ProcessFullUpdate( 235 ApplyUpdateResult V4Store::ProcessFullUpdate(
236 const std::string& metric,
212 const std::unique_ptr<ListUpdateResponse>& response) { 237 const std::unique_ptr<ListUpdateResponse>& response) {
213 DCHECK(response->has_response_type()); 238 DCHECK(response->has_response_type());
214 DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type()); 239 DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type());
215 // TODO(vakh): For a full update, we don't need to process the update in 240 // TODO(vakh): For a full update, we don't need to process the update in
216 // lexographical order to store it, but we do need to do that for calculating 241 // lexographical order to store it, but we do need to do that for calculating
217 // checksum. It might save some CPU cycles to store the full update as-is and 242 // checksum. It might save some CPU cycles to store the full update as-is and
218 // walk the list of hash prefixes in lexographical order only for checksum 243 // walk the list of hash prefixes in lexographical order only for checksum
219 // calculation. 244 // calculation.
220 return ProcessUpdate(HashPrefixMap(), response); 245 return ProcessUpdate(metric, HashPrefixMap(), response);
221 } 246 }
222 247
223 ApplyUpdateResult V4Store::ProcessUpdate( 248 ApplyUpdateResult V4Store::ProcessUpdate(
249 const std::string& metric,
224 const HashPrefixMap& hash_prefix_map_old, 250 const HashPrefixMap& hash_prefix_map_old,
225 const std::unique_ptr<ListUpdateResponse>& response) { 251 const std::unique_ptr<ListUpdateResponse>& response) {
226 const RepeatedField<int32>* raw_removals = nullptr; 252 const RepeatedField<int32>* raw_removals = nullptr;
227 RepeatedField<int32> rice_removals; 253 RepeatedField<int32> rice_removals;
228 size_t removals_size = response->removals_size(); 254 size_t removals_size = response->removals_size();
229 DCHECK_LE(removals_size, 1u); 255 DCHECK_LE(removals_size, 1u);
230 if (removals_size == 1) { 256 if (removals_size == 1) {
231 const ThreatEntrySet& removal = response->removals().Get(0); 257 const ThreatEntrySet& removal = response->removals().Get(0);
232 const CompressionType compression_type = removal.compression_type(); 258 const CompressionType compression_type = removal.compression_type();
233 if (compression_type == RAW) { 259 if (compression_type == RAW) {
234 raw_removals = &removal.raw_indices().indices(); 260 raw_removals = &removal.raw_indices().indices();
235 } else if (compression_type == RICE) { 261 } else if (compression_type == RICE) {
236 DCHECK(removal.has_rice_indices()); 262 DCHECK(removal.has_rice_indices());
237 263
238 const RiceDeltaEncoding& rice_indices = removal.rice_indices(); 264 const RiceDeltaEncoding& rice_indices = removal.rice_indices();
239 TimeTicks before = TimeTicks::Now(); 265 TimeTicks before = TimeTicks::Now();
240 V4DecodeResult decode_result = V4RiceDecoder::DecodeIntegers( 266 V4DecodeResult decode_result = V4RiceDecoder::DecodeIntegers(
241 rice_indices.first_value(), rice_indices.rice_parameter(), 267 rice_indices.first_value(), rice_indices.rice_parameter(),
242 rice_indices.num_entries(), rice_indices.encoded_data(), 268 rice_indices.num_entries(), rice_indices.encoded_data(),
243 &rice_removals); 269 &rice_removals);
244 270
245 RecordDecodeRemovalsResult(decode_result); 271 RecordDecodeRemovalsResult(metric, decode_result, store_path_);
246 if (decode_result != DECODE_SUCCESS) { 272 if (decode_result != DECODE_SUCCESS) {
247 return RICE_DECODING_FAILURE; 273 return RICE_DECODING_FAILURE;
248 } 274 }
249 RecordDecodeRemovalsTime(TimeTicks::Now() - before, store_path_); 275 RecordDecodeRemovalsTime(metric, TimeTicks::Now() - before, store_path_);
250 raw_removals = &rice_removals; 276 raw_removals = &rice_removals;
251 } else { 277 } else {
252 NOTREACHED() << "Unexpected compression_type type: " << compression_type; 278 NOTREACHED() << "Unexpected compression_type type: " << compression_type;
253 return UNEXPECTED_COMPRESSION_TYPE_REMOVALS_FAILURE; 279 return UNEXPECTED_COMPRESSION_TYPE_REMOVALS_FAILURE;
254 } 280 }
255 } 281 }
256 282
257 HashPrefixMap hash_prefix_map; 283 HashPrefixMap hash_prefix_map;
258 ApplyUpdateResult apply_update_result = 284 ApplyUpdateResult apply_update_result = UpdateHashPrefixMapFromAdditions(
259 UpdateHashPrefixMapFromAdditions(response->additions(), &hash_prefix_map); 285 metric, response->additions(), &hash_prefix_map);
260 if (apply_update_result != APPLY_UPDATE_SUCCESS) { 286 if (apply_update_result != APPLY_UPDATE_SUCCESS) {
261 return apply_update_result; 287 return apply_update_result;
262 } 288 }
263 289
264 std::string expected_checksum; 290 std::string expected_checksum;
265 if (response->has_checksum() && response->checksum().has_sha256()) { 291 if (response->has_checksum() && response->checksum().has_sha256()) {
266 expected_checksum = response->checksum().sha256(); 292 expected_checksum = response->checksum().sha256();
267 } 293 }
268 294
269 TimeTicks before = TimeTicks::Now(); 295 TimeTicks before = TimeTicks::Now();
270 apply_update_result = MergeUpdate(hash_prefix_map_old, hash_prefix_map, 296 apply_update_result = MergeUpdate(hash_prefix_map_old, hash_prefix_map,
271 raw_removals, expected_checksum); 297 raw_removals, expected_checksum);
272 if (apply_update_result != APPLY_UPDATE_SUCCESS) { 298 if (apply_update_result != APPLY_UPDATE_SUCCESS) {
273 return apply_update_result; 299 return apply_update_result;
274 } 300 }
275 RecordMergeUpdateTime(TimeTicks::Now() - before, store_path_); 301 RecordMergeUpdateTime(metric, TimeTicks::Now() - before, store_path_);
276 302
277 state_ = response->new_client_state(); 303 state_ = response->new_client_state();
278 return APPLY_UPDATE_SUCCESS; 304 return APPLY_UPDATE_SUCCESS;
279 } 305 }
280 306
281 void V4Store::ApplyUpdate( 307 void V4Store::ApplyUpdate(
282 std::unique_ptr<ListUpdateResponse> response, 308 std::unique_ptr<ListUpdateResponse> response,
283 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, 309 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner,
284 UpdatedStoreReadyCallback callback) { 310 UpdatedStoreReadyCallback callback) {
285 std::unique_ptr<V4Store> new_store( 311 std::unique_ptr<V4Store> new_store(new V4Store(task_runner_, store_path_));
286 new V4Store(this->task_runner_, this->store_path_));
287 ApplyUpdateResult apply_update_result; 312 ApplyUpdateResult apply_update_result;
313 std::string metric;
314 TimeTicks before = TimeTicks::Now();
288 if (response->response_type() == ListUpdateResponse::PARTIAL_UPDATE) { 315 if (response->response_type() == ListUpdateResponse::PARTIAL_UPDATE) {
316 metric = kProcessPartialUpdate;
289 apply_update_result = new_store->ProcessPartialUpdateAndWriteToDisk( 317 apply_update_result = new_store->ProcessPartialUpdateAndWriteToDisk(
290 hash_prefix_map_, std::move(response)); 318 metric, hash_prefix_map_, std::move(response));
291 } else if (response->response_type() == ListUpdateResponse::FULL_UPDATE) { 319 } else if (response->response_type() == ListUpdateResponse::FULL_UPDATE) {
320 metric = kProcessFullUpdate;
292 apply_update_result = 321 apply_update_result =
293 new_store->ProcessFullUpdateAndWriteToDisk(std::move(response)); 322 new_store->ProcessFullUpdateAndWriteToDisk(metric, std::move(response));
294 } else { 323 } else {
295 apply_update_result = UNEXPECTED_RESPONSE_TYPE_FAILURE; 324 apply_update_result = UNEXPECTED_RESPONSE_TYPE_FAILURE;
296 NOTREACHED() << "Failure: Unexpected response type: " 325 NOTREACHED() << "Failure: Unexpected response type: "
297 << response->response_type(); 326 << response->response_type();
298 } 327 }
299 328
300 if (apply_update_result == APPLY_UPDATE_SUCCESS) { 329 if (apply_update_result == APPLY_UPDATE_SUCCESS) {
330 RecordApplyUpdateTime(metric, TimeTicks::Now() - before, store_path_);
301 // new_store is done updating, pass it to the callback. 331 // new_store is done updating, pass it to the callback.
302 callback_task_runner->PostTask( 332 callback_task_runner->PostTask(
303 FROM_HERE, base::Bind(callback, base::Passed(&new_store))); 333 FROM_HERE, base::Bind(callback, base::Passed(&new_store)));
304 } else { 334 } else {
305 DVLOG(1) << "Failure: ApplyUpdate: reason: " << apply_update_result 335 DVLOG(1) << "Failure: ApplyUpdate: reason: " << apply_update_result
306 << "; store: " << *this; 336 << "; store: " << *this;
307 // new_store failed updating. Pass a nullptr to the callback. 337 // new_store failed updating. Pass a nullptr to the callback.
308 callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); 338 callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr));
309 } 339 }
310 340
311 RecordApplyUpdateResult(apply_update_result); 341 RecordApplyUpdateResult(metric, apply_update_result, store_path_);
312 } 342 }
313 343
314 ApplyUpdateResult V4Store::UpdateHashPrefixMapFromAdditions( 344 ApplyUpdateResult V4Store::UpdateHashPrefixMapFromAdditions(
345 const std::string& metric,
315 const RepeatedPtrField<ThreatEntrySet>& additions, 346 const RepeatedPtrField<ThreatEntrySet>& additions,
316 HashPrefixMap* additions_map) { 347 HashPrefixMap* additions_map) {
317 for (const auto& addition : additions) { 348 for (const auto& addition : additions) {
318 ApplyUpdateResult apply_update_result = APPLY_UPDATE_SUCCESS; 349 ApplyUpdateResult apply_update_result = APPLY_UPDATE_SUCCESS;
319 const CompressionType compression_type = addition.compression_type(); 350 const CompressionType compression_type = addition.compression_type();
320 if (compression_type == RAW) { 351 if (compression_type == RAW) {
321 DCHECK(addition.has_raw_hashes()); 352 DCHECK(addition.has_raw_hashes());
322 DCHECK(addition.raw_hashes().has_raw_hashes()); 353 DCHECK(addition.raw_hashes().has_raw_hashes());
323 354
324 apply_update_result = 355 apply_update_result =
325 AddUnlumpedHashes(addition.raw_hashes().prefix_size(), 356 AddUnlumpedHashes(addition.raw_hashes().prefix_size(),
326 addition.raw_hashes().raw_hashes(), additions_map); 357 addition.raw_hashes().raw_hashes(), additions_map);
327 } else if (compression_type == RICE) { 358 } else if (compression_type == RICE) {
328 DCHECK(addition.has_rice_hashes()); 359 DCHECK(addition.has_rice_hashes());
329 360
330 const RiceDeltaEncoding& rice_hashes = addition.rice_hashes(); 361 const RiceDeltaEncoding& rice_hashes = addition.rice_hashes();
331 std::vector<uint32_t> raw_hashes; 362 std::vector<uint32_t> raw_hashes;
332 TimeTicks before = TimeTicks::Now(); 363 TimeTicks before = TimeTicks::Now();
333 V4DecodeResult decode_result = V4RiceDecoder::DecodePrefixes( 364 V4DecodeResult decode_result = V4RiceDecoder::DecodePrefixes(
334 rice_hashes.first_value(), rice_hashes.rice_parameter(), 365 rice_hashes.first_value(), rice_hashes.rice_parameter(),
335 rice_hashes.num_entries(), rice_hashes.encoded_data(), &raw_hashes); 366 rice_hashes.num_entries(), rice_hashes.encoded_data(), &raw_hashes);
336 RecordDecodeAdditionsResult(decode_result); 367 RecordDecodeAdditionsResult(metric, decode_result, store_path_);
337 if (decode_result != DECODE_SUCCESS) { 368 if (decode_result != DECODE_SUCCESS) {
338 return RICE_DECODING_FAILURE; 369 return RICE_DECODING_FAILURE;
339 } else { 370 } else {
340 RecordDecodeAdditionsTime(TimeTicks::Now() - before, store_path_); 371 RecordDecodeAdditionsTime(metric, TimeTicks::Now() - before,
372 store_path_);
341 char* raw_hashes_start = reinterpret_cast<char*>(raw_hashes.data()); 373 char* raw_hashes_start = reinterpret_cast<char*>(raw_hashes.data());
342 size_t raw_hashes_size = sizeof(uint32_t) * raw_hashes.size(); 374 size_t raw_hashes_size = sizeof(uint32_t) * raw_hashes.size();
343 375
344 // Rice-Golomb encoding is used to send compressed compressed 4-byte 376 // Rice-Golomb encoding is used to send compressed compressed 4-byte
345 // hash prefixes. Hash prefixes longer than 4 bytes will not be 377 // hash prefixes. Hash prefixes longer than 4 bytes will not be
346 // compressed, and will be served in raw format instead. 378 // compressed, and will be served in raw format instead.
347 // Source: https://developers.google.com/safe-browsing/v4/compression 379 // Source: https://developers.google.com/safe-browsing/v4/compression
348 const PrefixSize kPrefixSize = 4; 380 const PrefixSize kPrefixSize = 4;
349 apply_update_result = AddUnlumpedHashes(kPrefixSize, raw_hashes_start, 381 apply_update_result = AddUnlumpedHashes(kPrefixSize, raw_hashes_start,
350 raw_hashes_size, additions_map); 382 raw_hashes_size, additions_map);
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 if (file_format.version_number() != kFileVersion) { 652 if (file_format.version_number() != kFileVersion) {
621 return FILE_VERSION_INCOMPATIBLE_FAILURE; 653 return FILE_VERSION_INCOMPATIBLE_FAILURE;
622 } 654 }
623 655
624 if (!file_format.has_list_update_response()) { 656 if (!file_format.has_list_update_response()) {
625 return HASH_PREFIX_INFO_MISSING_FAILURE; 657 return HASH_PREFIX_INFO_MISSING_FAILURE;
626 } 658 }
627 659
628 std::unique_ptr<ListUpdateResponse> response(new ListUpdateResponse); 660 std::unique_ptr<ListUpdateResponse> response(new ListUpdateResponse);
629 response->Swap(file_format.mutable_list_update_response()); 661 response->Swap(file_format.mutable_list_update_response());
630 ApplyUpdateResult apply_update_result = ProcessFullUpdate(response); 662 ApplyUpdateResult apply_update_result =
631 RecordApplyUpdateResultWhenReadingFromDisk(apply_update_result); 663 ProcessFullUpdate(kReadFromDisk, response);
664 RecordApplyUpdateResult(kReadFromDisk, apply_update_result, store_path_);
632 if (apply_update_result != APPLY_UPDATE_SUCCESS) { 665 if (apply_update_result != APPLY_UPDATE_SUCCESS) {
633 hash_prefix_map_.clear(); 666 hash_prefix_map_.clear();
634 return HASH_PREFIX_MAP_GENERATION_FAILURE; 667 return HASH_PREFIX_MAP_GENERATION_FAILURE;
635 } 668 }
636 RecordReadFromDiskTime(TimeTicks::Now() - before, store_path_); 669 RecordApplyUpdateTime(kReadFromDisk, TimeTicks::Now() - before, store_path_);
637 670
638 return READ_SUCCESS; 671 return READ_SUCCESS;
639 } 672 }
640 673
641 StoreWriteResult V4Store::WriteToDisk( 674 StoreWriteResult V4Store::WriteToDisk(
642 std::unique_ptr<ListUpdateResponse> response) const { 675 std::unique_ptr<ListUpdateResponse> response) const {
643 // Do not write partial updates to the disk. 676 // Do not write partial updates to the disk.
644 // After merging the updates, the ListUpdateResponse passed to this method 677 // After merging the updates, the ListUpdateResponse passed to this method
645 // should be a FULL_UPDATE. 678 // should be a FULL_UPDATE.
646 if (!response->has_response_type() || 679 if (!response->has_response_type() ||
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 776
744 // Find the next smallest unmerged element in the map. 777 // Find the next smallest unmerged element in the map.
745 has_unmerged = GetNextSmallestUnmergedPrefix(hash_prefix_map_, iterator_map, 778 has_unmerged = GetNextSmallestUnmergedPrefix(hash_prefix_map_, iterator_map,
746 &next_smallest_prefix); 779 &next_smallest_prefix);
747 } 780 }
748 781
749 char checksum[crypto::kSHA256Length]; 782 char checksum[crypto::kSHA256Length];
750 checksum_ctx->Finish(checksum, sizeof(checksum)); 783 checksum_ctx->Finish(checksum, sizeof(checksum));
751 for (size_t i = 0; i < crypto::kSHA256Length; i++) { 784 for (size_t i = 0; i < crypto::kSHA256Length; i++) {
752 if (checksum[i] != expected_checksum_[i]) { 785 if (checksum[i] != expected_checksum_[i]) {
753 RecordApplyUpdateResultWhenReadingFromDisk(CHECKSUM_MISMATCH_FAILURE); 786 RecordApplyUpdateResult(kReadFromDisk, CHECKSUM_MISMATCH_FAILURE,
787 store_path_);
754 #if DCHECK_IS_ON() 788 #if DCHECK_IS_ON()
755 std::string checksum_b64, expected_checksum_b64; 789 std::string checksum_b64, expected_checksum_b64;
756 base::Base64Encode(base::StringPiece(checksum, arraysize(checksum)), 790 base::Base64Encode(base::StringPiece(checksum, arraysize(checksum)),
757 &checksum_b64); 791 &checksum_b64);
758 base::Base64Encode(expected_checksum_, &expected_checksum_b64); 792 base::Base64Encode(expected_checksum_, &expected_checksum_b64);
759 DVLOG(1) << "Failure: Checksum mismatch: calculated: " << checksum_b64 793 DVLOG(1) << "Failure: Checksum mismatch: calculated: " << checksum_b64
760 << "; expected: " << expected_checksum_b64 794 << "; expected: " << expected_checksum_b64
761 << "; store: " << *this; 795 << "; store: " << *this;
762 #endif 796 #endif
763 return false; 797 return false;
764 } 798 }
765 } 799 }
766 return true; 800 return true;
767 } 801 }
768 802
769 } // namespace safe_browsing 803 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698