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,111 @@ |
+// 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 <vector> |
+ |
+#include "base/file_path.h" |
+#include "base/logging.h" |
+#include "base/metrics/histogram.h" |
+#include "base/platform_file.h" |
+#include "base/path_service.h" |
+ |
+namespace { |
+ |
+size_t ComputeRetrievalPointersBufferSize(int number_of_extents) { |
+ RETRIEVAL_POINTERS_BUFFER buffer; |
+ return sizeof(buffer) + (number_of_extents - 1) * sizeof(buffer.Extents); |
+} |
+ |
+} // namespace |
+ |
+namespace fragmentation_checker { |
+ |
+int CountFileExtents(const FilePath& file_path) { |
+ int file_extents_count = 0; |
+ |
+ base::PlatformFileError error_code = base::PLATFORM_FILE_ERROR_FAILED; |
+ base::PlatformFile file_handle = CreatePlatformFile( |
+ file_path, |
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, |
+ NULL, |
+ &error_code); |
+ if (error_code == base::PLATFORM_FILE_OK) { |
+ STARTING_VCN_INPUT_BUFFER starting_vcn_input_buffer = {0}; |
+ |
+ // Compute an output size capable of holding 16 extents at first. This will |
+ // fail when the number of extents exceeds 16, in which case we make |
+ // a bigger buffer capable of holding up to kMaxExtentCounts. |
+ int extents_guess = 16; |
+ size_t output_size = ComputeRetrievalPointersBufferSize(extents_guess); |
+ std::vector<uint8> retrieval_pointers_buffer(output_size); |
+ |
+ DWORD bytes_returned = 0; |
+ |
+ bool result = false; |
+ do { |
+ result = DeviceIoControl( |
+ 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) != FALSE; |
+ |
+ if (!result) { |
+ if (GetLastError() == ERROR_MORE_DATA) { |
+ // Grow the extents we can handle |
+ extents_guess *= 2; |
+ if (extents_guess > kMaxExtentCount) { |
+ LOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS output buffer exceeded " |
+ "maximum size."; |
+ file_extents_count = kMaxExtentCount; |
+ break; |
+ } |
+ output_size = ComputeRetrievalPointersBufferSize(extents_guess); |
+ retrieval_pointers_buffer.assign(output_size, 0); |
+ } else { |
+ PLOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS failed."; |
+ break; |
+ } |
+ } |
+ } while (!result); |
+ |
+ if (result) { |
+ RETRIEVAL_POINTERS_BUFFER* retrieval_pointers = |
+ reinterpret_cast<RETRIEVAL_POINTERS_BUFFER*>( |
+ &retrieval_pointers_buffer[0]); |
+ file_extents_count = static_cast<int>(retrieval_pointers->ExtentCount); |
+ } else { |
+ LOG(ERROR) << "Failed to retrieve extents."; |
+ } |
+ } else { |
+ LOG(ERROR) << "Failed to open module file to check extents. Error code = " |
+ << error_code; |
+ } |
+ |
+ return file_extents_count; |
+} |
+ |
+void RecordFragmentationMetricForCurrentModule() { |
+ FilePath module_path; |
+ if (PathService::Get(base::FILE_MODULE, &module_path)) { |
+ int file_extent_count = CountFileExtents(module_path); |
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Fragmentation.ModuleExtents", |
+ file_extent_count, |
+ 0, |
+ kMaxExtentCount, |
+ 50); |
+ } 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 |