/* * Copyright 2009, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Iterator over persisted metrics #include "persistent_iterator-win32.h" namespace stats_report { void PersistentMetricsIteratorWin32::Next() { current_value_.reset(); // Try to open the top-level key if we didn't already. if (NULL == key_.m_hKey) { HKEY parent_key = is_machine_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; LONG err = key_.Open(parent_key, key_name_, KEY_READ); if (err != ERROR_SUCCESS) return; } // Loop until we find a value while (state_ != kFinished) { if (NULL == sub_key_.m_hKey) { const wchar_t *subkey_name = NULL; switch (state_) { case kUninitialized: state_ = kCounts; subkey_name = kCountsKeyName; break; case kCounts: state_ = kTimings; subkey_name = kTimingsKeyName; break; case kTimings: state_ = kIntegers; subkey_name = kIntegersKeyName; break; case kIntegers: state_ = kBooleans; subkey_name = kBooleansKeyName; break; case kBooleans: state_ = kFinished; break; case kFinished: break; } if (NULL != subkey_name) { LONG err = sub_key_.Open(key_, subkey_name, KEY_READ); // go around the loop on error to try the next key type if (ERROR_SUCCESS != err) continue; } // reset value enumeration value_index_ = 0; } if (state_ != kFinished) { DCHECK(NULL != sub_key_.m_hKey); CString wide_value_name; DWORD value_name_len = 255; DWORD value_type = 0; BYTE buf[sizeof(TimingMetric::TimingData)]; DWORD value_len = sizeof(buf); // Get the next key and value LONG err = ::RegEnumValue(sub_key_, value_index_, CStrBuf(wide_value_name, value_name_len), &value_name_len, 0, &value_type, buf, &value_len); ++value_index_; if (ERROR_NO_MORE_ITEMS == err) { // done with this subkey, go around again sub_key_.Close(); continue; } else if (ERROR_SUCCESS != err) { // some other error, broken into a separate case for ease of debugging DCHECK(false && "Unexpected error during reg value enumeration"); } else { DCHECK(ERROR_SUCCESS == err); // convert value to ASCII current_value_name_ = wide_value_name; switch (state_) { case kCounts: if (value_len != sizeof(uint64)) continue; current_value_.reset( new CountMetric(current_value_name_ .GetString(), *reinterpret_cast(&buf[0]))); break; case kTimings: if (value_len != sizeof(TimingMetric::TimingData)) continue; current_value_.reset( new TimingMetric( current_value_name_.GetString(), *reinterpret_cast(&buf[0]))); break; case kIntegers: if (value_len != sizeof(uint64)) continue; current_value_.reset(new IntegerMetric( current_value_name_.GetString(), *reinterpret_cast(&buf[0]))); break; case kBooleans: if (value_len != sizeof(uint32)) continue; current_value_.reset( new BoolMetric(current_value_name_.GetString(), *reinterpret_cast(&buf[0]))); break; default: DCHECK(false && "Impossible state during reg value enumeration"); break; } if (current_value_.get()) return; } } } } } // namespace stats_report