Chromium Code Reviews| Index: chrome/browser/fragmentation_checker_win.cc |
| =================================================================== |
| --- chrome/browser/fragmentation_checker_win.cc (revision 0) |
| +++ chrome/browser/fragmentation_checker_win.cc (revision 0) |
| @@ -0,0 +1,143 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/fragmentation_checker_win.h" |
| + |
| +#include <windows.h> |
| +#include <winioctl.h> |
| + |
| +#include "base/at_exit.h" |
| +#include "base/basictypes.h" |
| +#include "base/command_line.h" |
| +#include "base/file_util.h" |
| +#include "base/logging.h" |
| +#include "base/metrics/histogram.h" |
| +#include "base/path_service.h" |
| + |
| +namespace { |
| + |
| +size_t kMaxBufferSize = 1 << 20; |
|
grt (UTC plus 2)
2011/09/30 18:44:14
const size_t...
robertshield
2011/09/30 19:53:00
Done.
|
| + |
| +struct FileExtentData { |
| + int number_of_extents; |
| + int64 virtual_cluster_span; |
| +}; |
| + |
| +size_t ComputeRetrievalPointersBufferSize(int number_of_extents) { |
| + return sizeof(RETRIEVAL_POINTERS_BUFFER) + |
| + (number_of_extents - 1) * (sizeof(LARGE_INTEGER) * 2); |
|
grt (UTC plus 2)
2011/09/30 18:44:14
indentation
grt (UTC plus 2)
2011/09/30 18:44:14
is it possible to replace sizeof(LARGE_INTEGER) *
robertshield
2011/09/30 19:53:00
Done.
robertshield
2011/09/30 19:53:00
Done.
|
| +} |
| + |
| +bool DumpFileExtents(const FilePath& file_path, |
| + FileExtentData* file_extent_data) { |
| + DCHECK(file_extent_data); |
| + if (!file_util::PathExists(file_path)) { |
|
grt (UTC plus 2)
2011/09/30 18:44:14
why do this extra check? CreatePlatformFile shoul
robertshield
2011/09/30 19:53:00
Done.
|
| + LOG(ERROR) << "File not found."; |
| + return false; |
| + } |
| + |
| + bool success = false; |
| + |
| + base::PlatformFileError error_code = base::PLATFORM_FILE_ERROR_FAILED; |
| + bool created = false; |
| + base::PlatformFile file_handle = CreatePlatformFile( |
| + file_path, |
| + base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, |
| + &created, |
| + &error_code); |
| + if (error_code == base::PLATFORM_FILE_OK && !created) { |
| + STARTING_VCN_INPUT_BUFFER starting_vcn_input_buffer = {0}; |
| + |
| + // Compute an output size capable of holding 16 extents at first. This may |
| + // fail when the number of extents exceeds 16, in which case we make |
| + // a bigger buffer up to kMaxBufferSize. |
| + int number_of_extents = 16; |
| + std::vector<BYTE> retrieval_pointers_buffer; |
|
grt (UTC plus 2)
2011/09/30 18:44:14
uint8 rather than win-specific BYTE?
robertshield
2011/09/30 19:53:00
Done, although this file is (and can only be) Wind
|
| + |
| + size_t output_size = ComputeRetrievalPointersBufferSize(number_of_extents); |
|
grt (UTC plus 2)
2011/09/30 18:44:14
do this computation before line 56, then change li
robertshield
2011/09/30 19:53:00
Done.
|
| + retrieval_pointers_buffer.resize(output_size); |
| + |
| + DWORD bytes_returned = 0; |
| + |
| + bool result = false; |
| + do { |
| + SetLastError(ERROR_SUCCESS); |
|
grt (UTC plus 2)
2011/09/30 18:44:14
this is extremely odd. please document why this i
robertshield
2011/09/30 19:53:00
rejiggered as discussed.
|
| + result = DeviceIoControl( |
|
grt (UTC plus 2)
2011/09/30 18:44:14
MSDN says that the call fails (returns 0) if the b
robertshield
2011/09/30 19:53:00
I found documentation suggesting using the GLE cod
|
| + file_handle, |
| + FSCTL_GET_RETRIEVAL_POINTERS, |
| + reinterpret_cast<void*>(&starting_vcn_input_buffer), |
| + sizeof(starting_vcn_input_buffer), |
| + reinterpret_cast<void*>(&retrieval_pointers_buffer[0]), |
| + retrieval_pointers_buffer.size(), |
| + &bytes_returned, |
| + NULL) == TRUE; |
|
grt (UTC plus 2)
2011/09/30 18:44:14
== TRUE -> != 0
MSDN says it returns zero/non-zero
robertshield
2011/09/30 19:53:00
My version of WinBase.h says it returns FALSE/TRUE
|
| + |
| + DWORD last_error = GetLastError(); |
|
grt (UTC plus 2)
2011/09/30 18:44:14
this is extremely odd. according to MSDN, you wou
robertshield
2011/09/30 19:53:00
Changed as discussed.
|
| + if (last_error == ERROR_MORE_DATA) { |
| + // Grow the extents we can handle |
| + number_of_extents *= 2; |
| + output_size = ComputeRetrievalPointersBufferSize(number_of_extents); |
| + |
| + if (output_size > kMaxBufferSize) { |
| + LOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS output buffer exceeded " |
| + "maximum size."; |
| + result = false; |
| + break; |
| + } |
| + |
| + retrieval_pointers_buffer.clear(); |
| + retrieval_pointers_buffer.resize(output_size); |
|
grt (UTC plus 2)
2011/09/30 18:44:14
replace these two lines with a call to .assign(out
robertshield
2011/09/30 19:53:00
Done.
|
| + } else { |
| + if (!result) { |
| + LOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS failed. gle = " |
|
grt (UTC plus 2)
2011/09/30 18:44:14
PLOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS faile
robertshield
2011/09/30 19:53:00
Done.
|
| + << last_error; |
| + } |
| + break; |
| + } |
| + } while (true); |
| + |
| + if (result) { |
| + RETRIEVAL_POINTERS_BUFFER* retrieval_pointers = |
| + reinterpret_cast<RETRIEVAL_POINTERS_BUFFER*>( |
| + &retrieval_pointers_buffer[0]); |
| + DWORD extent_count = retrieval_pointers->ExtentCount; |
| + LARGE_INTEGER extent_cluster_range = {0}; |
| + if (extent_count > 0) { |
| + extent_cluster_range.QuadPart = |
| + retrieval_pointers->Extents[extent_count - 1].NextVcn.QuadPart; |
| + extent_cluster_range.QuadPart -= |
| + retrieval_pointers->StartingVcn.QuadPart; |
| + } |
| + |
| + file_extent_data->number_of_extents = extent_count; |
|
grt (UTC plus 2)
2011/09/30 18:44:14
this does (in essence) a uint32 -> int conversion.
robertshield
2011/09/30 19:53:00
Done.
|
| + file_extent_data->virtual_cluster_span = extent_cluster_range.QuadPart; |
| + success = true; |
| + } else { |
| + LOG(ERROR) << "Failed to retrieve extents."; |
| + } |
| + } |
| + |
| + return success; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace fragmentation_checker { |
| + |
| +void RecordFragmentationMetricForCurrentModule() { |
| + FilePath module_path; |
|
grt (UTC plus 2)
2011/09/30 18:44:14
#include "base/file_path.h" for this
robertshield
2011/09/30 19:53:00
Done.
|
| + if (PathService::Get(base::FILE_MODULE, &module_path)) { |
| + FileExtentData file_extent_data = {0}; |
| + if (DumpFileExtents(module_path, &file_extent_data)) { |
| + UMA_HISTOGRAM_COUNTS("Fragmentation.ModuleExtents", |
| + file_extent_data.number_of_extents); |
| + UMA_HISTOGRAM_COUNTS("Fragmentation.ModuleSpan", |
| + file_extent_data.virtual_cluster_span); |
|
grt (UTC plus 2)
2011/09/30 18:44:14
1) this macro sets the max sample to 1000000, whic
robertshield
2011/09/30 19:53:00
As discussed, while reading the documentation agai
|
| + } |
| + } else { |
| + NOTREACHED() << "Could not get path to current module."; |
| + } |
| +} |
| + |
| +} // namespace fragmentation_checker |
| Property changes on: chrome\browser\fragmentation_checker_win.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |