| Index: net/base/file_stream.cc | 
| diff --git a/net/base/file_stream.cc b/net/base/file_stream.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..aae50c2d14ccb092f72b05fcbb4f8c61d776a44c | 
| --- /dev/null | 
| +++ b/net/base/file_stream.cc | 
| @@ -0,0 +1,251 @@ | 
| +// 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 "net/base/file_stream.h" | 
| + | 
| +#include <string> | 
| +#if defined(OS_WIN) | 
| +#include <windows.h> | 
| +#endif | 
| + | 
| +#include "base/basictypes.h" | 
| +#include "base/logging.h" | 
| +#include "base/metrics/histogram.h" | 
| + | 
| +namespace net { | 
| + | 
| +namespace { | 
| + | 
| +int g_recording_class_mask = RECORDING_CLASS_NONE; | 
| + | 
| +#if  defined(OS_WIN) | 
| + | 
| +struct Range { | 
| +  int low; | 
| +  int high; | 
| +  bool record_individually; | 
| +}; | 
| + | 
| +// This must be higher than the largest value that isn't remapped into a bucket. | 
| +int kErrorBucketStart = 400; | 
| + | 
| +Range kErrorRangeList[] = { | 
| +  { 0, 321, true },  // These are the ones we don't remap into buckets. | 
| +  { 335, 371, false }, | 
| +  { 383, 387, false }, | 
| +  { 399, 404, false }, | 
| +  { 415, 418, false }, | 
| +  { 431, 433, false }, | 
| +  { 447, 868, false }, | 
| +  { 994, 1471, false }, | 
| +  { 1500, 1513, false }, | 
| +  { 1536, 1553, false }, | 
| +  { 1601, 1654, false }, | 
| +  { 1700, 1834, false }, | 
| +  { 1898, 1938, false }, | 
| +  { 2000, 2024, false }, | 
| +  { 2048, 2085, false }, | 
| +  { 2108, 2110, false }, | 
| +  { 2202, 2203, false }, | 
| +  { 2250, 2251, false }, | 
| +  { 2401, 2405, false }, | 
| +  { 3000, 3021, false }, | 
| +  { 3950, 3951, false }, | 
| +  { 4000, 4007, false }, | 
| +  { 4050, 4066, false }, | 
| +  { 4096, 4116, false }, | 
| +  { 4200, 4215, false }, | 
| +  { 4300, 4353, false }, | 
| +  { 4390, 4395, false }, | 
| +  { 4500, 4501, false }, | 
| +  { 4864, 4905, false }, | 
| +  { 5001, 5090, false }, | 
| +  { 5890, 5953, false }, | 
| +  { 6000, 6023, false }, | 
| +  { 6118, 6119, false }, | 
| +  { 6200, 6201, false }, | 
| +  { 6600, 6649, false }, | 
| +  { 6700, 6732, false }, | 
| +  { 6800, 6856, false }, | 
| +  { 7001, 7071, false }, | 
| +  { 8001, 8018, false }, | 
| +  { 8192, 8263, false }, | 
| +  { 8301, 8640, false }, | 
| +  { 8704, 8705, false }, | 
| +  { 8960, 9053, false }, | 
| +  { 9216, 9218, false }, | 
| +  { 9263, 9276, false }, | 
| +  { 9472, 9506, false }, | 
| +  { 9550, 9573, false }, | 
| +  { 9600, 9622, false }, | 
| +  { 9650, 9656, false }, | 
| +  { 9688, 9723, false }, | 
| +  { 9750, 9754, false }, | 
| +  { 9800, 9802, false }, | 
| +  { 9850, 9853, false }, | 
| +  { 9900, 9907, false }, | 
| +  { 10000, 10072, false }, | 
| +  { 10091, 10113, false }, | 
| +  { 11001, 11034, false }, | 
| +  { 12288, 12335, false }, | 
| +  { 12544, 12559, false }, | 
| +  { 12595, 12597, false }, | 
| +  { 12801, 12803, false }, | 
| +  { 13000, 13026, false }, | 
| +  { 13800, 13933, false }, | 
| +  { 14000, 14111, false }, | 
| +  { 15000, 15039, false }, | 
| +  { 15080, 15086, false }, | 
| +  { 15100, 15109, false }, | 
| +  { 15200, 15208, false }, | 
| +  { 15250, 15251, false }, | 
| +  { 15299, 15302, false }, | 
| +  { 16385, 16436, false }, | 
| +  { 18432, 18454, false }, | 
| +  { 20480, 20486, false }, | 
| +  { 24577, 24607, false }, | 
| +  { 28673, 28698, false }, | 
| +  { 32790, 32816, false }, | 
| +  { 33281, 33322, false }, | 
| +  { 35005, 35024, false }, | 
| +  { 36000, 36004, false }, | 
| +  { 40010, 40011, false }, | 
| +  { 40067, 40069, false }, | 
| +  { 53248, 53293, false }, | 
| +  { 53376, 53382, false }, | 
| +  { 57344, 57360, false }, | 
| +  { 57377, 57394, false }, | 
| +  { 65535, 65536 } | 
| +}; | 
| +size_t kNumErrorRanges = ARRAYSIZE_UNSAFE(kErrorRangeList); | 
| + | 
| +// Windows has very many errors.  We're not interested in most of them, but we | 
| +// don't know which ones are significant. | 
| +// This function maps error ranges we think we don't care about to specific | 
| +// buckets, and leaves the others alone.  If we get hits on the buckets, | 
| +// we can add those values to the values we leave alone. | 
| +// If we get values *between* the buckets, we record those as buckets too. | 
| +// The range list is extracted from WinError.h. | 
| +int ReduceErrorRange(int error) { | 
| +  error = HRESULT_CODE(error); | 
| + | 
| +  for (size_t n = 0; n < kNumErrorRanges; ++n) { | 
| +    if (kErrorRangeList[n].record_individually) { | 
| +      if (error < kErrorRangeList[n].low) | 
| +        return kErrorBucketStart + (2 * n) - 1;  // In gap before the bucket. | 
| +      if (error <= kErrorRangeList[n].high) | 
| +        return error;  // Record individually. | 
| +    } else { | 
| +      if (error < kErrorRangeList[n].low) | 
| +        return kErrorBucketStart + (2 * n) - 1;  // In gap before the bucket. | 
| +      if (error <= kErrorRangeList[n].high) | 
| +        return kErrorBucketStart + 2 * n;  // In bucket. | 
| +    } | 
| +  } | 
| + | 
| +  // After the last bucket. | 
| +  return kErrorBucketStart + 2 * kNumErrorRanges; | 
| +} | 
| + | 
| +#endif  // defined(OS_WIN) | 
| + | 
| +void RecordFileErrorTypeCount(FileErrorTypes type) { | 
| +  UMA_HISTOGRAM_ENUMERATION( | 
| +      "FileErrorType.Counts", type, FILE_ERROR_TYPES_COUNT); | 
| +} | 
| + | 
| +std::string RecordUmaName(FileErrorTypes type, int class_flags) { | 
| +  std::string s; | 
| +  static const char* names[] = { | 
| +    "FileErrorTypes.NotOpenError", | 
| +    "FileErrorTypes.OpenError", | 
| +    "FileErrorTypes.WriteError", | 
| +    "FileErrorTypes.ReadError", | 
| +    "FileErrorTypes.SeekError", | 
| +    "FileErrorTypes.FlushError", | 
| +    "FileErrorTypes.SetEofError", | 
| +    "FileErrorTypes.GetSizeError", | 
| +  }; | 
| +  static const char* classes[] = { | 
| +    ".Download", | 
| +    // Add more strings here as necessary to match |RecordingClass| items. | 
| +  }; | 
| +  static const int num_classes = ARRAYSIZE_UNSAFE(classes); | 
| + | 
| +  s = names[type]; | 
| + | 
| +  int i; | 
| +  int mask; | 
| +  int start = RECORDING_CLASS_NONE + 1; | 
| +  for (i = start, mask = 1 << (start - 1); | 
| +       i < (num_classes + start); | 
| +       mask <<= 1, i++) { | 
| +    if (class_flags & mask) { | 
| +      s += classes[i - start]; | 
| +      break; | 
| +    } | 
| +  } | 
| + | 
| +  return s; | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +void EnableRecordingForClass(int class_flags) { | 
| +  g_recording_class_mask = class_flags; | 
| +} | 
| + | 
| +#define UMA_HISTOGRAM_CLASS(c) \ | 
| +  if (class_flags & (1 << RECORDING_CLASS_##c) & g_recording_class_mask) { \ | 
| +    UMA_HISTOGRAM_ENUMERATION(name.c_str(), error, max_error); \ | 
| +    break; \ | 
| +  } | 
| + | 
| +#define UMA_HISTOGRAM_CLASSES() \ | 
| +  for (int i = 0; i < RECORDING_CLASS_MAX; ++i) { \ | 
| +    UMA_HISTOGRAM_CLASS(DOWNLOADS) \ | 
| +  } | 
| + | 
| +#define UMA_HISTOGRAM_TYPE(t) \ | 
| +  case FILE_ERROR_TYPES_##t: \ | 
| +    UMA_HISTOGRAM_CLASSES() \ | 
| +    break; | 
| + | 
| +void RecordFileError(int error, FileErrorTypes type, int class_flags) { | 
| +  if (class_flags == RECORDING_CLASS_NONE) | 
| +    return; | 
| + | 
| +  RecordFileErrorTypeCount(type); | 
| + | 
| +  std::string name = RecordUmaName(type, class_flags); | 
| + | 
| +  DLOG(WARNING) << "() " << "Recording error " << error | 
| +                << " of type " << type << " with flags " << class_flags | 
| +                << ". Name = '" << name << "'"; | 
| + | 
| +  unsigned int max_error = (1U << 14) - 2;  // Histogram limit. | 
| + | 
| +#if  defined(OS_WIN) | 
| +  error = ReduceErrorRange(error); | 
| +  max_error = kErrorBucketStart + 2 * kNumErrorRanges + 1; | 
| +#elif  defined(OS_POSIX) | 
| +  // Posix errors seem to have only low positive values. | 
| +  max_error = 160; | 
| +#endif | 
| + | 
| +  switch(type) { | 
| +    UMA_HISTOGRAM_TYPE(IS_NOT_OPEN) | 
| +    UMA_HISTOGRAM_TYPE(OPEN) | 
| +    UMA_HISTOGRAM_TYPE(WRITE) | 
| +    UMA_HISTOGRAM_TYPE(READ) | 
| +    UMA_HISTOGRAM_TYPE(SEEK) | 
| +    UMA_HISTOGRAM_TYPE(FLUSH) | 
| +    UMA_HISTOGRAM_TYPE(SET_EOF) | 
| +    UMA_HISTOGRAM_TYPE(GET_SIZE) | 
| +    default: | 
| +      break; | 
| +  } | 
| +} | 
| + | 
| +}  // namespace net | 
|  |