Revert 6747 "Refactor StatsCollector and associated types."

Breakes FYI bots.

BUG=N/A
TBR=ajm@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/18889004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6770 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrike@webrtc.org 2014-07-23 21:38:58 +00:00
parent 8721f989bf
commit 8c7e3291a9
7 changed files with 144 additions and 242 deletions

View File

@ -85,12 +85,11 @@ struct SetSessionDescriptionMsg : public talk_base::MessageData {
}; };
struct GetStatsMsg : public talk_base::MessageData { struct GetStatsMsg : public talk_base::MessageData {
GetStatsMsg(webrtc::StatsObserver* observer, explicit GetStatsMsg(webrtc::StatsObserver* observer)
webrtc::MediaStreamTrackInterface* track) : observer(observer) {
: observer(observer), track(track) {
} }
webrtc::StatsReports reports;
talk_base::scoped_refptr<webrtc::StatsObserver> observer; talk_base::scoped_refptr<webrtc::StatsObserver> observer;
talk_base::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
}; };
// |in_str| should be of format // |in_str| should be of format
@ -447,15 +446,17 @@ talk_base::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
bool PeerConnection::GetStats(StatsObserver* observer, bool PeerConnection::GetStats(StatsObserver* observer,
MediaStreamTrackInterface* track, MediaStreamTrackInterface* track,
StatsOutputLevel level) { StatsOutputLevel level) {
ASSERT(signaling_thread()->IsCurrent());
if (!VERIFY(observer != NULL)) { if (!VERIFY(observer != NULL)) {
LOG(LS_ERROR) << "GetStats - observer is NULL."; LOG(LS_ERROR) << "GetStats - observer is NULL.";
return false; return false;
} }
stats_->UpdateStats(level); stats_->UpdateStats(level);
signaling_thread()->Post(this, MSG_GETSTATS, talk_base::scoped_ptr<GetStatsMsg> msg(new GetStatsMsg(observer));
new GetStatsMsg(observer, track)); if (!stats_->GetStats(track, &(msg->reports))) {
return false;
}
signaling_thread()->Post(this, MSG_GETSTATS, msg.release());
return true; return true;
} }
@ -701,9 +702,7 @@ void PeerConnection::OnMessage(talk_base::Message* msg) {
} }
case MSG_GETSTATS: { case MSG_GETSTATS: {
GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
StatsReports reports; param->observer->OnComplete(param->reports);
stats_->GetStats(param->track, &reports);
param->observer->OnComplete(reports);
delete param; delete param;
break; break;
} }

View File

@ -113,18 +113,7 @@ class StreamCollectionInterface : public talk_base::RefCountInterface {
class StatsObserver : public talk_base::RefCountInterface { class StatsObserver : public talk_base::RefCountInterface {
public: public:
// TODO(tommi): Remove. virtual void OnComplete(const std::vector<StatsReport>& reports) = 0;
virtual void OnComplete(const std::vector<StatsReport>& reports) {}
// TODO(tommi): Make pure virtual and remove implementation.
virtual void OnComplete(const StatsReports& reports) {
std::vector<StatsReportCopyable> report_copies;
for (size_t i = 0; i < reports.size(); ++i)
report_copies.push_back(StatsReportCopyable(*reports[i]));
std::vector<StatsReport>* r =
reinterpret_cast<std::vector<StatsReport>*>(&report_copies);
OnComplete(*r);
}
protected: protected:
virtual ~StatsObserver() {} virtual ~StatsObserver() {}

View File

@ -234,6 +234,7 @@ void StatsReport::ReplaceValue(StatsReport::StatsValueName name,
} }
namespace { namespace {
typedef std::map<std::string, StatsReport> StatsMap;
double GetTimeNow() { double GetTimeNow() {
return talk_base::Timing::WallTimeNow() * talk_base::kNumMillisecsPerSec; return talk_base::Timing::WallTimeNow() * talk_base::kNumMillisecsPerSec;
@ -293,16 +294,17 @@ bool ExtractValueFromReport(
return false; return false;
} }
void AddTrackReport(StatsSet* reports, const std::string& track_id) { void AddTrackReport(StatsMap* reports, const std::string& track_id) {
// Adds an empty track report. // Adds an empty track report.
StatsReport* report = reports->FindOrAddNew( StatsReport report;
StatsId(StatsReport::kStatsReportTypeTrack, track_id)); report.type = StatsReport::kStatsReportTypeTrack;
report->type = StatsReport::kStatsReportTypeTrack; report.id = StatsId(StatsReport::kStatsReportTypeTrack, track_id);
report->AddValue(StatsReport::kStatsValueNameTrackId, track_id); report.AddValue(StatsReport::kStatsValueNameTrackId, track_id);
(*reports)[report.id] = report;
} }
template <class TrackVector> template <class TrackVector>
void CreateTrackReports(const TrackVector& tracks, StatsSet* reports) { void CreateTrackReports(const TrackVector& tracks, StatsMap* reports) {
for (size_t j = 0; j < tracks.size(); ++j) { for (size_t j = 0; j < tracks.size(); ++j) {
webrtc::MediaStreamTrackInterface* track = tracks[j]; webrtc::MediaStreamTrackInterface* track = tracks[j];
AddTrackReport(reports, track->id()); AddTrackReport(reports, track->id());
@ -467,7 +469,7 @@ void ExtractStats(const cricket::BandwidthEstimationInfo& info,
double stats_gathering_started, double stats_gathering_started,
PeerConnectionInterface::StatsOutputLevel level, PeerConnectionInterface::StatsOutputLevel level,
StatsReport* report) { StatsReport* report) {
ASSERT(report->id == StatsReport::kStatsReportVideoBweId); report->id = StatsReport::kStatsReportVideoBweId;
report->type = StatsReport::kStatsReportTypeBwe; report->type = StatsReport::kStatsReportTypeBwe;
// Clear out stats from previous GatherStats calls if any. // Clear out stats from previous GatherStats calls if any.
@ -581,9 +583,9 @@ void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track,
// Create the kStatsReportTypeTrack report for the new track if there is no // Create the kStatsReportTypeTrack report for the new track if there is no
// report yet. // report yet.
StatsReport* found = reports_.Find( StatsMap::iterator it = reports_.find(
StatsId(StatsReport::kStatsReportTypeTrack, audio_track->id())); StatsId(StatsReport::kStatsReportTypeTrack, audio_track->id()));
if (!found) if (it == reports_.end())
AddTrackReport(&reports_, audio_track->id()); AddTrackReport(&reports_, audio_track->id());
} }
@ -601,46 +603,49 @@ void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track,
ASSERT(false); ASSERT(false);
} }
void StatsCollector::GetStats(MediaStreamTrackInterface* track, bool StatsCollector::GetStats(MediaStreamTrackInterface* track,
StatsReports* reports) { StatsReports* reports) {
ASSERT(reports != NULL); ASSERT(reports != NULL);
ASSERT(reports->empty()); reports->clear();
StatsMap::iterator it;
if (!track) { if (!track) {
StatsSet::const_iterator it; for (it = reports_.begin(); it != reports_.end(); ++it) {
for (it = reports_.begin(); it != reports_.end(); ++it) reports->push_back(it->second);
reports->push_back(&(*it)); }
return; return true;
} }
StatsReport* report = it = reports_.find(StatsId(StatsReport::kStatsReportTypeSession,
reports_.Find(StatsId(StatsReport::kStatsReportTypeSession,
session_->id())); session_->id()));
if (report) if (it != reports_.end()) {
reports->push_back(report); reports->push_back(it->second);
}
report = reports_.Find( it = reports_.find(StatsId(StatsReport::kStatsReportTypeTrack, track->id()));
StatsId(StatsReport::kStatsReportTypeTrack, track->id()));
if (!report) if (it == reports_.end()) {
return; LOG(LS_WARNING) << "No StatsReport is available for "<< track->id();
return false;
}
reports->push_back(report); reports->push_back(it->second);
std::string track_id; std::string track_id;
for (StatsSet::const_iterator it = reports_.begin(); it != reports_.end(); for (it = reports_.begin(); it != reports_.end(); ++it) {
++it) { if (it->second.type != StatsReport::kStatsReportTypeSsrc) {
if (it->type != StatsReport::kStatsReportTypeSsrc)
continue; continue;
}
if (ExtractValueFromReport(*it, if (ExtractValueFromReport(it->second,
StatsReport::kStatsValueNameTrackId, StatsReport::kStatsValueNameTrackId,
&track_id)) { &track_id)) {
if (track_id == track->id()) { if (track_id == track->id()) {
reports->push_back(&(*it)); reports->push_back(it->second);
} }
} }
} }
return true;
} }
void void
@ -667,13 +672,13 @@ StatsReport* StatsCollector::PrepareLocalReport(
const std::string& transport_id, const std::string& transport_id,
TrackDirection direction) { TrackDirection direction) {
const std::string ssrc_id = talk_base::ToString<uint32>(ssrc); const std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
StatsReport* report = reports_.Find( StatsMap::iterator it = reports_.find(StatsId(
StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id, direction)); StatsReport::kStatsReportTypeSsrc, ssrc_id, direction));
// Use the ID of the track that is currently mapped to the SSRC, if any. // Use the ID of the track that is currently mapped to the SSRC, if any.
std::string track_id; std::string track_id;
if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) {
if (!report) { if (it == reports_.end()) {
// The ssrc is not used by any track or existing report, return NULL // The ssrc is not used by any track or existing report, return NULL
// in such case to indicate no report is prepared for the ssrc. // in such case to indicate no report is prepared for the ssrc.
return NULL; return NULL;
@ -681,13 +686,13 @@ StatsReport* StatsCollector::PrepareLocalReport(
// The ssrc is not used by any existing track. Keeps the old track id // The ssrc is not used by any existing track. Keeps the old track id
// since we want to report the stats for inactive ssrc. // since we want to report the stats for inactive ssrc.
ExtractValueFromReport(*report, ExtractValueFromReport(it->second,
StatsReport::kStatsValueNameTrackId, StatsReport::kStatsValueNameTrackId,
&track_id); &track_id);
} }
report = GetOrCreateReport( StatsReport* report = GetOrCreateReport(StatsReport::kStatsReportTypeSsrc,
StatsReport::kStatsReportTypeSsrc, ssrc_id, direction); ssrc_id, direction);
// Clear out stats from previous GatherStats calls if any. // Clear out stats from previous GatherStats calls if any.
// This is required since the report will be returned for the new values. // This is required since the report will be returned for the new values.
@ -710,13 +715,13 @@ StatsReport* StatsCollector::PrepareRemoteReport(
const std::string& transport_id, const std::string& transport_id,
TrackDirection direction) { TrackDirection direction) {
const std::string ssrc_id = talk_base::ToString<uint32>(ssrc); const std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
StatsReport* report = reports_.Find( StatsMap::iterator it = reports_.find(StatsId(
StatsId(StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction)); StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction));
// Use the ID of the track that is currently mapped to the SSRC, if any. // Use the ID of the track that is currently mapped to the SSRC, if any.
std::string track_id; std::string track_id;
if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) {
if (!report) { if (it == reports_.end()) {
// The ssrc is not used by any track or existing report, return NULL // The ssrc is not used by any track or existing report, return NULL
// in such case to indicate no report is prepared for the ssrc. // in such case to indicate no report is prepared for the ssrc.
return NULL; return NULL;
@ -724,12 +729,12 @@ StatsReport* StatsCollector::PrepareRemoteReport(
// The ssrc is not used by any existing track. Keeps the old track id // The ssrc is not used by any existing track. Keeps the old track id
// since we want to report the stats for inactive ssrc. // since we want to report the stats for inactive ssrc.
ExtractValueFromReport(*report, ExtractValueFromReport(it->second,
StatsReport::kStatsValueNameTrackId, StatsReport::kStatsValueNameTrackId,
&track_id); &track_id);
} }
report = GetOrCreateReport( StatsReport* report = GetOrCreateReport(
StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction); StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction);
// Clear out stats from previous GatherStats calls if any. // Clear out stats from previous GatherStats calls if any.
@ -773,17 +778,18 @@ std::string StatsCollector::AddOneCertificateReport(
talk_base::Base64::EncodeFromArray( talk_base::Base64::EncodeFromArray(
der_buffer.data(), der_buffer.length(), &der_base64); der_buffer.data(), der_buffer.length(), &der_base64);
StatsReport* report = reports_.FindOrAddNew( StatsReport report;
StatsId(StatsReport::kStatsReportTypeCertificate, fingerprint)); report.type = StatsReport::kStatsReportTypeCertificate;
report->type = StatsReport::kStatsReportTypeCertificate; report.id = StatsId(report.type, fingerprint);
report->timestamp = stats_gathering_started_; report.timestamp = stats_gathering_started_;
report->AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint); report.AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint);
report->AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm, report.AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm,
digest_algorithm); digest_algorithm);
report->AddValue(StatsReport::kStatsValueNameDer, der_base64); report.AddValue(StatsReport::kStatsValueNameDer, der_base64);
if (!issuer_id.empty()) if (!issuer_id.empty())
report->AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id); report.AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id);
return report->id; reports_[report.id] = report;
return report.id;
} }
std::string StatsCollector::AddCertificateReports( std::string StatsCollector::AddCertificateReports(
@ -813,14 +819,16 @@ std::string StatsCollector::AddCertificateReports(
void StatsCollector::ExtractSessionInfo() { void StatsCollector::ExtractSessionInfo() {
// Extract information from the base session. // Extract information from the base session.
StatsReport* report = reports_.FindOrAddNew(StatsId( StatsReport report;
StatsReport::kStatsReportTypeSession, session_->id())); report.id = StatsId(StatsReport::kStatsReportTypeSession, session_->id());
report->type = StatsReport::kStatsReportTypeSession; report.type = StatsReport::kStatsReportTypeSession;
report->timestamp = stats_gathering_started_; report.timestamp = stats_gathering_started_;
report->values.clear(); report.values.clear();
report->AddBoolean(StatsReport::kStatsValueNameInitiator, report.AddBoolean(StatsReport::kStatsValueNameInitiator,
session_->initiator()); session_->initiator());
reports_[report.id] = report;
cricket::SessionStats stats; cricket::SessionStats stats;
if (session_->GetStats(&stats)) { if (session_->GetStats(&stats)) {
// Store the proxy map away for use in SSRC reporting. // Store the proxy map away for use in SSRC reporting.
@ -849,58 +857,61 @@ void StatsCollector::ExtractSessionInfo() {
= transport_iter->second.channel_stats.begin(); = transport_iter->second.channel_stats.begin();
channel_iter != transport_iter->second.channel_stats.end(); channel_iter != transport_iter->second.channel_stats.end();
++channel_iter) { ++channel_iter) {
StatsReport channel_report;
std::ostringstream ostc; std::ostringstream ostc;
ostc << "Channel-" << transport_iter->second.content_name ostc << "Channel-" << transport_iter->second.content_name
<< "-" << channel_iter->component; << "-" << channel_iter->component;
StatsReport* channel_report = reports_.FindOrAddNew(ostc.str()); channel_report.id = ostc.str();
channel_report->type = StatsReport::kStatsReportTypeComponent; channel_report.type = StatsReport::kStatsReportTypeComponent;
channel_report->timestamp = stats_gathering_started_; channel_report.timestamp = stats_gathering_started_;
channel_report->AddValue(StatsReport::kStatsValueNameComponent, channel_report.AddValue(StatsReport::kStatsValueNameComponent,
channel_iter->component); channel_iter->component);
if (!local_cert_report_id.empty()) if (!local_cert_report_id.empty())
channel_report->AddValue( channel_report.AddValue(
StatsReport::kStatsValueNameLocalCertificateId, StatsReport::kStatsValueNameLocalCertificateId,
local_cert_report_id); local_cert_report_id);
if (!remote_cert_report_id.empty()) if (!remote_cert_report_id.empty())
channel_report->AddValue( channel_report.AddValue(
StatsReport::kStatsValueNameRemoteCertificateId, StatsReport::kStatsValueNameRemoteCertificateId,
remote_cert_report_id); remote_cert_report_id);
reports_[channel_report.id] = channel_report;
for (size_t i = 0; for (size_t i = 0;
i < channel_iter->connection_infos.size(); i < channel_iter->connection_infos.size();
++i) { ++i) {
StatsReport report;
const cricket::ConnectionInfo& info
= channel_iter->connection_infos[i];
std::ostringstream ost; std::ostringstream ost;
ost << "Conn-" << transport_iter->first << "-" ost << "Conn-" << transport_iter->first << "-"
<< channel_iter->component << "-" << i; << channel_iter->component << "-" << i;
StatsReport* report = reports_.FindOrAddNew(ost.str()); report.id = ost.str();
report->type = StatsReport::kStatsReportTypeCandidatePair; report.type = StatsReport::kStatsReportTypeCandidatePair;
report->timestamp = stats_gathering_started_; report.timestamp = stats_gathering_started_;
// Link from connection to its containing channel. // Link from connection to its containing channel.
report->AddValue(StatsReport::kStatsValueNameChannelId, report.AddValue(StatsReport::kStatsValueNameChannelId,
channel_report->id); channel_report.id);
report.AddValue(StatsReport::kStatsValueNameBytesSent,
const cricket::ConnectionInfo& info =
channel_iter->connection_infos[i];
report->AddValue(StatsReport::kStatsValueNameBytesSent,
info.sent_total_bytes); info.sent_total_bytes);
report->AddValue(StatsReport::kStatsValueNameBytesReceived, report.AddValue(StatsReport::kStatsValueNameBytesReceived,
info.recv_total_bytes); info.recv_total_bytes);
report->AddBoolean(StatsReport::kStatsValueNameWritable, report.AddBoolean(StatsReport::kStatsValueNameWritable,
info.writable); info.writable);
report->AddBoolean(StatsReport::kStatsValueNameReadable, report.AddBoolean(StatsReport::kStatsValueNameReadable,
info.readable); info.readable);
report->AddBoolean(StatsReport::kStatsValueNameActiveConnection, report.AddBoolean(StatsReport::kStatsValueNameActiveConnection,
info.best_connection); info.best_connection);
report->AddValue(StatsReport::kStatsValueNameLocalAddress, report.AddValue(StatsReport::kStatsValueNameLocalAddress,
info.local_candidate.address().ToString()); info.local_candidate.address().ToString());
report->AddValue(StatsReport::kStatsValueNameRemoteAddress, report.AddValue(StatsReport::kStatsValueNameRemoteAddress,
info.remote_candidate.address().ToString()); info.remote_candidate.address().ToString());
report->AddValue(StatsReport::kStatsValueNameRtt, info.rtt); report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
report->AddValue(StatsReport::kStatsValueNameTransportType, report.AddValue(StatsReport::kStatsValueNameTransportType,
info.local_candidate.protocol()); info.local_candidate.protocol());
report->AddValue(StatsReport::kStatsValueNameLocalCandidateType, report.AddValue(StatsReport::kStatsValueNameLocalCandidateType,
info.local_candidate.type()); info.local_candidate.type());
report->AddValue(StatsReport::kStatsValueNameRemoteCandidateType, report.AddValue(StatsReport::kStatsValueNameRemoteCandidateType,
info.remote_candidate.type()); info.remote_candidate.type());
reports_[report.id] = report;
} }
} }
} }
@ -957,8 +968,7 @@ void StatsCollector::ExtractVideoInfo(
if (video_info.bw_estimations.size() != 1) { if (video_info.bw_estimations.size() != 1) {
LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size();
} else { } else {
StatsReport* report = StatsReport* report = &reports_[StatsReport::kStatsReportVideoBweId];
reports_.FindOrAddNew(StatsReport::kStatsReportVideoBweId);
ExtractStats( ExtractStats(
video_info.bw_estimations[0], stats_gathering_started_, level, report); video_info.bw_estimations[0], stats_gathering_started_, level, report);
} }
@ -969,7 +979,13 @@ StatsReport* StatsCollector::GetReport(const std::string& type,
TrackDirection direction) { TrackDirection direction) {
ASSERT(type == StatsReport::kStatsReportTypeSsrc || ASSERT(type == StatsReport::kStatsReportTypeSsrc ||
type == StatsReport::kStatsReportTypeRemoteSsrc); type == StatsReport::kStatsReportTypeRemoteSsrc);
return reports_.Find(StatsId(type, id, direction)); std::string statsid = StatsId(type, id, direction);
StatsReport* report = NULL;
std::map<std::string, StatsReport>::iterator it = reports_.find(statsid);
if (it != reports_.end())
report = &(it->second);
return report;
} }
StatsReport* StatsCollector::GetOrCreateReport(const std::string& type, StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
@ -980,8 +996,8 @@ StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
StatsReport* report = GetReport(type, id, direction); StatsReport* report = GetReport(type, id, direction);
if (report == NULL) { if (report == NULL) {
std::string statsid = StatsId(type, id, direction); std::string statsid = StatsId(type, id, direction);
report = reports_.FindOrAddNew(statsid); report = &reports_[statsid]; // Create new element.
ASSERT(report->id == statsid); report->id = statsid;
report->type = type; report->type = type;
} }

View File

@ -72,11 +72,7 @@ class StatsCollector {
// be called before this function to get the most recent stats. |selector| is // be called before this function to get the most recent stats. |selector| is
// a track label or empty string. The most recent reports are stored in // a track label or empty string. The most recent reports are stored in
// |reports|. // |reports|.
// TODO(tommi): Change this contract to accept a callback object instead bool GetStats(MediaStreamTrackInterface* track,
// of filling in |reports|. As is, there's a requirement that the caller
// uses |reports| immediately without allowing any async activity on
// the thread (message handling etc) and then discard the results.
void GetStats(MediaStreamTrackInterface* track,
StatsReports* reports); StatsReports* reports);
// Prepare an SSRC report for the given ssrc. Used internally // Prepare an SSRC report for the given ssrc. Used internally
@ -125,7 +121,7 @@ class StatsCollector {
TrackDirection direction); TrackDirection direction);
// A map from the report id to the report. // A map from the report id to the report.
StatsSet reports_; std::map<std::string, StatsReport> reports_;
// Raw pointer to the session the statistics are gathered from. // Raw pointer to the session the statistics are gathered from.
WebRtcSession* const session_; WebRtcSession* const session_;
double stats_gathering_started_; double stats_gathering_started_;

View File

@ -168,10 +168,10 @@ std::string ExtractStatsValue(const std::string& type,
return kNoReports; return kNoReports;
} }
for (size_t i = 0; i < reports.size(); ++i) { for (size_t i = 0; i < reports.size(); ++i) {
if (reports[i]->type != type) if (reports[i].type != type)
continue; continue;
std::string ret; std::string ret;
if (GetValue(reports[i], name, &ret)) { if (GetValue(&reports[i], name, &ret)) {
return ret; return ret;
} }
} }
@ -184,10 +184,10 @@ std::string ExtractStatsValue(const std::string& type,
const StatsReport* FindNthReportByType( const StatsReport* FindNthReportByType(
const StatsReports& reports, const std::string& type, int n) { const StatsReports& reports, const std::string& type, int n) {
for (size_t i = 0; i < reports.size(); ++i) { for (size_t i = 0; i < reports.size(); ++i) {
if (reports[i]->type == type) { if (reports[i].type == type) {
n--; n--;
if (n == 0) if (n == 0)
return reports[i]; return &reports[i];
} }
} }
return NULL; return NULL;
@ -196,8 +196,8 @@ const StatsReport* FindNthReportByType(
const StatsReport* FindReportById(const StatsReports& reports, const StatsReport* FindReportById(const StatsReports& reports,
const std::string& id) { const std::string& id) {
for (size_t i = 0; i < reports.size(); ++i) { for (size_t i = 0; i < reports.size(); ++i) {
if (reports[i]->id == id) { if (reports[i].id == id) {
return reports[i]; return &reports[i];
} }
} }
return NULL; return NULL;
@ -433,7 +433,7 @@ void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) {
class StatsCollectorTest : public testing::Test { class StatsCollectorTest : public testing::Test {
protected: protected:
StatsCollectorTest() StatsCollectorTest()
: media_engine_(new cricket::FakeMediaEngine()), : media_engine_(new cricket::FakeMediaEngine),
channel_manager_( channel_manager_(
new cricket::ChannelManager(media_engine_, new cricket::ChannelManager(media_engine_,
new cricket::FakeDeviceManager(), new cricket::FakeDeviceManager(),
@ -443,8 +443,6 @@ class StatsCollectorTest : public testing::Test {
EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false)); EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
} }
~StatsCollectorTest() {}
// This creates a standard setup with a transport called "trspname" // This creates a standard setup with a transport called "trspname"
// having one transport channel // having one transport channel
// and the specified virtual connection name. // and the specified virtual connection name.
@ -788,7 +786,7 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
stats.GetStats(NULL, &reports); stats.GetStats(NULL, &reports);
EXPECT_EQ((size_t)1, reports.size()); EXPECT_EQ((size_t)1, reports.size());
EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack), EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack),
reports[0]->type); reports[0].type);
std::string trackValue = std::string trackValue =
ExtractStatsValue(StatsReport::kStatsReportTypeTrack, ExtractStatsValue(StatsReport::kStatsReportTypeTrack,
@ -834,7 +832,6 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
EXPECT_TRUE(track_report); EXPECT_TRUE(track_report);
// Get report for the specific |track|. // Get report for the specific |track|.
reports.clear();
stats.GetStats(track_, &reports); stats.GetStats(track_, &reports);
// |reports| should contain at least one session report, one track report, // |reports| should contain at least one session report, one track report,
// and one ssrc report. // and one ssrc report.
@ -1336,7 +1333,7 @@ TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
webrtc::StatsCollector stats(&session_); // Implementation under test. webrtc::StatsCollector stats(&session_); // Implementation under test.
// Ignore unused callback (logspam). // Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_)) EXPECT_CALL(session_, GetTransport(_))
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL))); .WillOnce(Return(static_cast<cricket::Transport*>(NULL)));
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
// The content_name known by the voice channel. // The content_name known by the voice channel.
const std::string kVcName("vcname"); const std::string kVcName("vcname");
@ -1399,7 +1396,6 @@ TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
VerifyVoiceSenderInfoReport(track_report, voice_sender_info); VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
// Get stats for the remote track. // Get stats for the remote track.
reports.clear();
stats.GetStats(remote_track.get(), &reports); stats.GetStats(remote_track.get(), &reports);
track_report = FindNthReportByType(reports, track_report = FindNthReportByType(reports,
StatsReport::kStatsReportTypeSsrc, 1); StatsReport::kStatsReportTypeSsrc, 1);
@ -1456,7 +1452,6 @@ TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) {
cricket::VoiceSenderInfo new_voice_sender_info; cricket::VoiceSenderInfo new_voice_sender_info;
InitVoiceSenderInfo(&new_voice_sender_info); InitVoiceSenderInfo(&new_voice_sender_info);
cricket::VoiceMediaInfo new_stats_read; cricket::VoiceMediaInfo new_stats_read;
reports.clear();
SetupAndVerifyAudioTrackStats( SetupAndVerifyAudioTrackStats(
new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName, new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName,
media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports);

View File

@ -31,7 +31,6 @@
#ifndef TALK_APP_WEBRTC_STATSTYPES_H_ #ifndef TALK_APP_WEBRTC_STATSTYPES_H_
#define TALK_APP_WEBRTC_STATSTYPES_H_ #define TALK_APP_WEBRTC_STATSTYPES_H_
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -40,45 +39,15 @@
namespace webrtc { namespace webrtc {
// TODO(tommi): Move all the implementation that's in this file and
// statscollector.cc related to these types, into a new, statstypes.cc file.
class StatsReport { class StatsReport {
protected:
// TODO(tommi): Disallow copy ctor etc completely once not needed.
explicit StatsReport(const StatsReport& src)
: id(src.id),
type(src.type),
timestamp(src.timestamp),
values(src.values) {}
StatsReport& operator=(const StatsReport& src) {
ASSERT(id == src.id);
type = src.type;
timestamp = src.timestamp;
values = src.values;
return *this;
}
// Constructor is protected to force use of StatsSet.
explicit StatsReport(const std::string& id) : id(id), timestamp(0) {}
public: public:
// Operators provided for STL container/algorithm support. StatsReport() : timestamp(0) { }
bool operator<(const StatsReport& other) const { return id < other.id; }
bool operator==(const StatsReport& other) const { return id == other.id; }
// Special support for being able to use std::find on a container
// without requiring a new StatsReport instance.
bool operator==(const std::string& other_id) const { return id == other_id; }
// TODO(tommi): Change this to be an enum type that holds all the // TODO(tommi): Change this to be an enum type that holds all the
// kStatsValueName constants. // kStatsValueName constants.
typedef const char* StatsValueName; typedef const char* StatsValueName;
// The unique identifier for this object. std::string id; // See below for contents.
// This is used as a key for this report in ordered containers,
// so it must never be changed.
const std::string id; // See below for contents.
std::string type; // See below for contents. std::string type; // See below for contents.
struct Value { struct Value {
@ -270,65 +239,7 @@ class StatsReport {
static const char kStatsValueNameDecodingPLCCNG[]; static const char kStatsValueNameDecodingPLCCNG[];
}; };
// This class is provided for the cases where we need to keep typedef std::vector<StatsReport> StatsReports;
// snapshots of reports around. This is an edge case.
// TODO(tommi): Move into the private section of StatsSet.
class StatsReportCopyable : public StatsReport {
public:
StatsReportCopyable(const std::string& id) : StatsReport(id) {}
explicit StatsReportCopyable(const StatsReport& src)
: StatsReport(src) {}
using StatsReport::operator=;
};
// Typedef for an array of const StatsReport pointers.
// Ownership of the pointers held by this implementation is assumed to lie
// elsewhere and lifetime guarantees are made by the implementation that uses
// this type. In the StatsCollector, object ownership lies with the StatsSet
// class.
typedef std::vector<const StatsReport*> StatsReports;
// A map from the report id to the report.
// This class wraps an STL container and provides a limited set of
// functionality in order to keep things simple.
// TODO(tommi): Use a thread checker here (currently not in libjingle).
class StatsSet {
public:
StatsSet() {}
~StatsSet() {}
typedef std::set<StatsReportCopyable> Container;
typedef Container::iterator iterator;
typedef Container::const_iterator const_iterator;
const_iterator begin() const { return list_.begin(); }
const_iterator end() const { return list_.end(); }
// Creates a new report object with |id| that does not already
// exist in the list of reports.
StatsReport* InsertNew(const std::string& id) {
ASSERT(Find(id) == NULL);
const StatsReport* ret = &(*list_.insert(StatsReportCopyable(id)).first);
return const_cast<StatsReport*>(ret);
}
StatsReport* FindOrAddNew(const std::string& id) {
StatsReport* ret = Find(id);
return ret ? ret : InsertNew(id);
}
// Looks for a report with the given |id|. If one is not found, NULL
// will be returned.
StatsReport* Find(const std::string& id) {
const_iterator it = std::find(begin(), end(), id);
return it == end() ? NULL :
const_cast<StatsReport*>(static_cast<const StatsReport*>(&(*it)));
}
private:
Container list_;
};
} // namespace webrtc } // namespace webrtc

View File

@ -120,13 +120,9 @@ class MockStatsObserver : public webrtc::StatsObserver {
MockStatsObserver() MockStatsObserver()
: called_(false) {} : called_(false) {}
virtual ~MockStatsObserver() {} virtual ~MockStatsObserver() {}
virtual void OnComplete(const StatsReports& reports) { virtual void OnComplete(const std::vector<webrtc::StatsReport>& reports) {
called_ = true; called_ = true;
reports_.clear(); reports_ = reports;
reports_.reserve(reports.size());
StatsReports::const_iterator it;
for (it = reports.begin(); it != reports.end(); ++it)
reports_.push_back(StatsReportCopyable(*(*it)));
} }
bool called() const { return called_; } bool called() const { return called_; }
@ -152,7 +148,7 @@ class MockStatsObserver : public webrtc::StatsObserver {
} }
private: private:
int GetSsrcStatsValue(StatsReport::StatsValueName name) { int GetSsrcStatsValue(const std::string name) {
if (reports_.empty()) { if (reports_.empty()) {
return 0; return 0;
} }
@ -171,7 +167,7 @@ class MockStatsObserver : public webrtc::StatsObserver {
} }
bool called_; bool called_;
std::vector<StatsReportCopyable> reports_; std::vector<webrtc::StatsReport> reports_;
}; };
} // namespace webrtc } // namespace webrtc