Index: chrome/browser/net/passive_log_collector.h |
=================================================================== |
--- chrome/browser/net/passive_log_collector.h (revision 48758) |
+++ chrome/browser/net/passive_log_collector.h (working copy) |
@@ -5,6 +5,7 @@ |
#ifndef CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ |
#define CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ |
+#include <deque> |
#include <string> |
#include <vector> |
@@ -15,6 +16,21 @@ |
#include "chrome/browser/net/chrome_net_log.h" |
#include "net/base/net_log.h" |
+// PassiveLogCollector watches the NetLog event stream, and saves the network |
+// event for recent requests, in a circular buffer. |
+// |
+// This is done so that when a network problem is encountered (performance |
+// problem, or error), about:net-internals can be opened shortly after the |
+// problem and it will contain a trace for the problem request. |
+// |
+// (This is in contrast to the "active logging" which captures every single |
+// network event, but requires capturing to have been enabled *prior* to |
+// encountering the problem. Active capturing is enabled as long as |
+// about:net-internals is open). |
+// |
+// The data captured by PassiveLogCollector is grouped by NetLog::Source, into |
+// a RequestInfo structure. These in turn are grouped by NetLog::SourceType, and |
+// owned by a RequestTrackerBase instance for the specific source type. |
class PassiveLogCollector : public ChromeNetLog::Observer { |
public: |
// This structure encapsulates all of the parameters of a captured event, |
@@ -40,16 +56,13 @@ |
}; |
typedef std::vector<Entry> EntryList; |
+ typedef std::vector<net::NetLog::Source> SourceDependencyList; |
+ // TODO(eroman): Rename to SourceInfo. |
struct RequestInfo { |
RequestInfo() |
: source_id(net::NetLog::Source::kInvalidId), |
- num_entries_truncated(0), |
- total_bytes_transmitted(0), |
- total_bytes_received(0), |
- bytes_transmitted(0), |
- bytes_received(0), |
- last_tx_rx_position(0) {} |
+ num_entries_truncated(0), reference_count(0), is_alive(true) {} |
// Returns the URL that corresponds with this source. This is |
// only meaningful for certain source types (URL_REQUEST, SOCKET_STREAM). |
@@ -59,15 +72,21 @@ |
uint32 source_id; |
EntryList entries; |
size_t num_entries_truncated; |
- net::NetLog::Source subordinate_source; |
- // Only used in SocketTracker. |
- uint64 total_bytes_transmitted; |
- uint64 total_bytes_received; |
- uint64 bytes_transmitted; |
- uint64 bytes_received; |
- uint32 last_tx_rx_position; // The |order| of the last Tx or Rx entry. |
- base::TimeTicks last_tx_rx_time; // The |time| of the last Tx or Rx entry. |
+ // List of other sources which contain information relevant to this |
+ // request (for example, a url request might depend on the log items |
+ // for a connect job and for a socket that were bound to it.) |
+ SourceDependencyList dependencies; |
+ |
+ // Holds the count of how many other sources have added this as a |
+ // dependent source. When it is 0, it means noone has referenced it so it |
+ // can be deleted normally. |
+ int reference_count; |
+ |
+ // |is_alive| is set to false once the request has been added to the |
+ // tracker's graveyard (it may still be kept around due to a non-zero |
+ // reference_count, but it is still considered "dead"). |
+ bool is_alive; |
}; |
typedef std::vector<RequestInfo> RequestInfoList; |
@@ -76,19 +95,32 @@ |
// URLRequests/SocketStreams/ConnectJobs. |
class RequestTrackerBase { |
public: |
- explicit RequestTrackerBase(size_t max_graveyard_size); |
+ RequestTrackerBase(size_t max_graveyard_size, PassiveLogCollector* parent); |
+ virtual ~RequestTrackerBase(); |
+ |
void OnAddEntry(const Entry& entry); |
- RequestInfoList GetLiveRequests() const; |
- void ClearRecentlyDeceased(); |
- RequestInfoList GetRecentlyDeceased() const; |
- |
+ // Clears all the passively logged data from this tracker. |
void Clear(); |
// Appends all the captured entries to |out|. The ordering is undefined. |
void AppendAllEntries(EntryList* out) const; |
+#ifdef UNIT_TEST |
+ // Helper used to inspect the current state by unit-tests. |
+ // Retuns a copy of the requests held by the tracker. |
+ RequestInfoList GetAllDeadOrAliveRequests(bool is_alive) const { |
+ RequestInfoList result; |
+ for (SourceIDToInfoMap::const_iterator it = requests_.begin(); |
+ it != requests_.end(); ++it) { |
+ if (it->second.is_alive == is_alive) |
+ result.push_back(it->second); |
+ } |
+ return result; |
+ } |
+#endif |
+ |
protected: |
enum Action { |
ACTION_NONE, |
@@ -96,30 +128,46 @@ |
ACTION_MOVE_TO_GRAVEYARD, |
}; |
- // Finds a request, either in the live entries or the graveyard and returns |
- // it. |
- RequestInfo* GetRequestInfo(uint32 id); |
+ // Makes |info| hold a reference to |source|. This way |source| will be |
+ // kept alive at least as long as |info|. |
+ void AddReferenceToSourceDependency(const net::NetLog::Source& source, |
+ RequestInfo* info); |
- // When GetLiveRequests() is called, RequestTrackerBase calls this method |
- // for each entry after adding it to the list which will be returned |
- // to the caller. |
- virtual void OnLiveRequest(RequestInfo* info) const {} |
- |
private: |
typedef base::hash_map<uint32, RequestInfo> SourceIDToInfoMap; |
+ typedef std::deque<uint32> DeletionQueue; |
// Updates |out_info| with the information from |entry|. Returns an action |
// to perform for this map entry on completion. |
virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info) = 0; |
- void RemoveFromLiveRequests(uint32 source_id); |
- void InsertIntoGraveyard(const RequestInfo& info); |
+ // Removes |source_id| from |requests_|. This also releases any references |
+ // to dependencies held by this source. |
+ void DeleteRequestInfo(uint32 source_id); |
- SourceIDToInfoMap live_requests_; |
+ // Adds |source_id| to the FIFO queue (graveyard) for deletion. |
+ void AddToDeletionQueue(uint32 source_id); |
+ |
+ // Adds/Releases a reference from the source with ID |source_id|. |
+ // Use |offset=-1| to do a release, and |offset=1| for an addref. |
+ void AdjustReferenceCountForSource(int offset, uint32 source_id); |
+ |
+ // Releases all the references to sources held by |info|. |
+ void ReleaseAllReferencesToDependencies(RequestInfo* info); |
+ |
+ // This map contains all of the requests being tracked by this tracker. |
+ // (It includes both the "live" requests, and the "dead" ones.) |
+ SourceIDToInfoMap requests_; |
+ |
size_t max_graveyard_size_; |
- size_t next_graveyard_index_; |
- RequestInfoList graveyard_; |
+ // FIFO queue for entries in |requests_| that are no longer alive, and |
+ // can be deleted. This buffer is also called "graveyard" elsewhere. We |
+ // queue requests for deletion so they can persist a bit longer. |
+ DeletionQueue deletion_queue_; |
+ |
+ PassiveLogCollector* parent_; |
+ |
DISALLOW_COPY_AND_ASSIGN(RequestTrackerBase); |
}; |
@@ -128,10 +176,8 @@ |
public: |
static const size_t kMaxGraveyardSize; |
- ConnectJobTracker(); |
+ explicit ConnectJobTracker(PassiveLogCollector* parent); |
- void AppendLogEntries(RequestInfo* out_info, uint32 connect_id); |
- |
protected: |
virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
private: |
@@ -145,14 +191,10 @@ |
SocketTracker(); |
- void AppendLogEntries(RequestInfo* out_info, uint32 socket_id, bool clear); |
- |
protected: |
virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
private: |
- void ClearInfo(RequestInfo* info); |
- |
DISALLOW_COPY_AND_ASSIGN(SocketTracker); |
}; |
@@ -161,39 +203,27 @@ |
public: |
static const size_t kMaxGraveyardSize; |
- RequestTracker(ConnectJobTracker* connect_job_tracker, |
- SocketTracker* socket_tracker); |
+ explicit RequestTracker(PassiveLogCollector* parent); |
- void IntegrateSubordinateSource(RequestInfo* info, |
- bool clear_entries) const; |
- |
protected: |
virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
- virtual void OnLiveRequest(RequestInfo* info) const { |
- IntegrateSubordinateSource(info, false); |
- } |
- |
private: |
- ConnectJobTracker* connect_job_tracker_; |
- SocketTracker* socket_tracker_; |
- |
DISALLOW_COPY_AND_ASSIGN(RequestTracker); |
}; |
- // Tracks the log entries for the last seen SOURCE_INIT_PROXY_RESOLVER. |
- class InitProxyResolverTracker { |
+ // Specialization of RequestTrackerBase for handling |
+ // SOURCE_INIT_PROXY_RESOLVER. |
+ class InitProxyResolverTracker : public RequestTrackerBase { |
public: |
+ static const size_t kMaxGraveyardSize; |
+ |
InitProxyResolverTracker(); |
- void OnAddEntry(const Entry& entry); |
+ protected: |
+ virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
- const EntryList& entries() const { |
- return entries_; |
- } |
- |
private: |
- EntryList entries_; |
DISALLOW_COPY_AND_ASSIGN(InitProxyResolverTracker); |
}; |
@@ -221,32 +251,20 @@ |
net::NetLog::EventPhase phase, |
net::NetLog::EventParameters* params); |
+ // Returns the tracker to use for sources of type |source_type|, or NULL. |
+ RequestTrackerBase* GetTrackerForSourceType( |
+ net::NetLog::SourceType source_type); |
+ |
// Clears all of the passively logged data. |
void Clear(); |
- RequestTracker* url_request_tracker() { |
- return &url_request_tracker_; |
- } |
- |
- RequestTracker* socket_stream_tracker() { |
- return &socket_stream_tracker_; |
- } |
- |
- InitProxyResolverTracker* init_proxy_resolver_tracker() { |
- return &init_proxy_resolver_tracker_; |
- } |
- |
- SpdySessionTracker* spdy_session_tracker() { |
- return &spdy_session_tracker_; |
- } |
- |
// Fills |out| with the full list of events that have been passively |
// captured. The list is ordered by capture time. |
void GetAllCapturedEvents(EntryList* out) const; |
private: |
- FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, LostConnectJob); |
- FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, LostSocket); |
+ FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, |
+ HoldReferenceToDependentSource); |
ConnectJobTracker connect_job_tracker_; |
SocketTracker socket_tracker_; |
@@ -255,6 +273,11 @@ |
InitProxyResolverTracker init_proxy_resolver_tracker_; |
SpdySessionTracker spdy_session_tracker_; |
+ // This array maps each NetLog::SourceType to one of the tracker instances |
+ // defined above. Use of this array avoid duplicating the list of trackers |
+ // elsewhere. |
+ RequestTrackerBase* trackers_[net::NetLog::SOURCE_COUNT]; |
+ |
// The count of how many events have flowed through this log. Used to set the |
// "order" field on captured events. |
uint32 num_events_seen_; |