Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/mtransport/rlogconnector.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=2 et sw=2 tw=80: */
3
4
/* This Source Code Form is subject to the terms of the Mozilla Public
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8
/* Original author: bcampen@mozilla.com */
9
10
#include <cstdarg>
11
12
#include "rlogconnector.h"
13
14
#include <deque>
15
#include <string>
16
#include "logging.h"
17
#include "mozilla/Assertions.h"
18
#include "mozilla/Move.h" // Pinch hitting for <utility> and std::move
19
#include "mozilla/Mutex.h"
20
#include "mozilla/Sprintf.h"
21
#include <vector>
22
23
extern "C" {
24
#include <csi_platform.h>
25
#include "r_log.h"
26
#include "registry.h"
27
}
28
29
/* Matches r_dest_vlog type defined in r_log.h */
30
static int ringbuffer_vlog(int facility,
31
                           int level,
32
                           const char *format,
33
0
                           va_list ap) {
34
0
  MOZ_ASSERT(mozilla::RLogConnector::GetInstance());
35
0
  // I could be evil and printf right into a std::string, but unless this
36
0
  // shows up in profiling, it is not worth doing.
37
0
  char temp[4096];
38
0
  VsprintfLiteral(temp, format, ap);
39
0
40
0
  mozilla::RLogConnector::GetInstance()->Log(level, std::string(temp));
41
0
  return 0;
42
0
}
43
44
static mozilla::LogLevel rLogLvlToMozLogLvl(int level) {
45
  switch (level) {
46
    case LOG_EMERG:
47
    case LOG_ALERT:
48
    case LOG_CRIT:
49
    case LOG_ERR:
50
      return mozilla::LogLevel::Error;
51
    case LOG_WARNING:
52
      return mozilla::LogLevel::Warning;
53
    case LOG_NOTICE:
54
      return mozilla::LogLevel::Info;
55
    case LOG_INFO:
56
      return mozilla::LogLevel::Debug;
57
    case LOG_DEBUG:
58
    default:
59
      return mozilla::LogLevel::Verbose;
60
  }
61
}
62
63
MOZ_MTLOG_MODULE("nicer");
64
65
namespace mozilla {
66
67
RLogConnector* RLogConnector::instance;
68
69
RLogConnector::RLogConnector()
70
  : log_limit_(4096),
71
    mutex_("RLogConnector::mutex_"),
72
0
    disableCount_(0) {
73
0
}
74
75
0
RLogConnector::~RLogConnector() {
76
0
}
77
78
0
void RLogConnector::SetLogLimit(uint32_t new_limit) {
79
0
  OffTheBooksMutexAutoLock lock(mutex_);
80
0
  log_limit_ = new_limit;
81
0
  RemoveOld();
82
0
}
83
84
0
void RLogConnector::Log(int level, std::string&& log) {
85
0
  MOZ_MTLOG(rLogLvlToMozLogLvl(level), log);
86
0
87
0
  if (level <= LOG_INFO) {
88
0
    OffTheBooksMutexAutoLock lock(mutex_);
89
0
    if (disableCount_ == 0) {
90
0
      AddMsg(std::move(log));
91
0
    }
92
0
  }
93
0
}
94
95
0
void RLogConnector::AddMsg(std::string&& msg) {
96
0
  log_messages_.push_front(std::move(msg));
97
0
  RemoveOld();
98
0
}
99
100
0
inline void RLogConnector::RemoveOld() {
101
0
  if (log_messages_.size() > log_limit_) {
102
0
    log_messages_.resize(log_limit_);
103
0
  }
104
0
}
105
106
0
RLogConnector* RLogConnector::CreateInstance() {
107
0
  if (!instance) {
108
0
    instance = new RLogConnector;
109
0
    NR_reg_init(NR_REG_MODE_LOCAL);
110
0
    r_log_set_extra_destination(LOG_DEBUG, &ringbuffer_vlog);
111
0
  }
112
0
  return instance;
113
0
}
114
115
0
RLogConnector* RLogConnector::GetInstance() {
116
0
  return instance;
117
0
}
118
119
0
void RLogConnector::DestroyInstance() {
120
0
  // First param is ignored when passing null
121
0
  r_log_set_extra_destination(LOG_DEBUG, nullptr);
122
0
  delete instance;
123
0
  instance = nullptr;
124
0
}
125
126
// As long as at least one PeerConnection exists in a Private Window rlog messages will not
127
// be saved in the RLogConnector. This is necessary because the log_messages buffer
128
// is shared across all instances of PeerConnectionImpls. There is no way with the current
129
// structure of r_log to run separate logs.
130
131
0
void RLogConnector::EnterPrivateMode() {
132
0
  OffTheBooksMutexAutoLock lock(mutex_);
133
0
  ++disableCount_;
134
0
  MOZ_ASSERT(disableCount_ != 0);
135
0
136
0
  if (disableCount_ == 1) {
137
0
    AddMsg("LOGGING SUSPENDED: a connection is active in a Private Window ***");
138
0
  }
139
0
}
140
141
0
void RLogConnector::ExitPrivateMode() {
142
0
  OffTheBooksMutexAutoLock lock(mutex_);
143
0
  MOZ_ASSERT(disableCount_ != 0);
144
0
145
0
  if (--disableCount_ == 0) {
146
0
    AddMsg("LOGGING RESUMED: no connections are active in a Private Window ***");
147
0
  }
148
0
}
149
150
0
void RLogConnector::Clear() {
151
0
  OffTheBooksMutexAutoLock lock(mutex_);
152
0
  log_messages_.clear();
153
0
}
154
155
void RLogConnector::Filter(const std::string& substring,
156
                            uint32_t limit,
157
0
                            std::deque<std::string>* matching_logs) {
158
0
  std::vector<std::string> substrings;
159
0
  substrings.push_back(substring);
160
0
  FilterAny(substrings, limit, matching_logs);
161
0
}
162
163
inline bool AnySubstringMatches(const std::vector<std::string>& substrings,
164
0
                                const std::string& string) {
165
0
  for (auto sub = substrings.begin(); sub != substrings.end(); ++sub) {
166
0
    if (string.find(*sub) != std::string::npos) {
167
0
      return true;
168
0
    }
169
0
  }
170
0
  return false;
171
0
}
172
173
void RLogConnector::FilterAny(const std::vector<std::string>& substrings,
174
                               uint32_t limit,
175
0
                               std::deque<std::string>* matching_logs) {
176
0
  OffTheBooksMutexAutoLock lock(mutex_);
177
0
  if (limit == 0) {
178
0
    // At a max, all of the log messages.
179
0
    limit = log_limit_;
180
0
  }
181
0
182
0
  for (auto log = log_messages_.begin();
183
0
       log != log_messages_.end() && matching_logs->size() < limit;
184
0
       ++log) {
185
0
    if (AnySubstringMatches(substrings, *log)) {
186
0
      matching_logs->push_front(*log);
187
0
    }
188
0
  }
189
0
}
190
191
} // namespace mozilla