blob: 7bb4cc65c6c54d510eb1be155511d8526ba928ae [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_SYSTEM_MONITOR_LIB_DOCKYARD_DOCKYARD_H_
#define SRC_DEVELOPER_SYSTEM_MONITOR_LIB_DOCKYARD_DOCKYARD_H_
#include <stdint.h>
#include <atomic>
#include <functional>
#include <iostream>
#include <map>
#include <mutex>
#include <set>
#include <sstream>
#include <string>
#include <thread>
#include <vector>
class SystemMonitorDockyardHostTest;
namespace grpc {
class Server;
} // namespace grpc
namespace dockyard {
class DockyardServiceImpl;
class SystemMonitorDockyardTest;
// An integer value representing a dockyard path.
typedef uint32_t DockyardId;
constexpr DockyardId INVALID_DOCKYARD_ID = 0;
// Sample time stamp in nanoseconds.
typedef uint64_t SampleTimeNs;
// The data type of a sample value.
typedef uint64_t SampleValue;
// This is not intended to remain a std::map. This works fine for small numbers
// of samples and it has the API desired. So a std::map is being used while
// framing out the API.
using SampleStream = std::map<SampleTimeNs, SampleValue>;
// This is clearer than using the raw number.
constexpr SampleTimeNs kNanosecondsPerSecond = 1000000000;
constexpr SampleTimeNs kSampleTimeInfinite = UINT64_MAX;
// Special value for missing sample stream.
constexpr SampleValue NO_STREAM = (SampleValue)-1ULL;
// Special value for missing data.
constexpr SampleValue NO_DATA = (SampleValue)-2ULL;
// The highest value for sample data.
constexpr SampleValue SAMPLE_MAX_VALUE = (SampleValue)-3ULL;
// The slope value is scaled up to preserve decimal precision when using an
// integer value. To convert the slope integer (slope_value) to floating point:
// float slope_as_percentage = float(slope_value) * SLOPE_SCALE.
constexpr SampleValue SLOPE_LIMIT = 1000000ULL;
constexpr float SLOPE_SCALE = 100.0f / static_cast<float>(SLOPE_LIMIT);
// The upper value used to represent zero to one values with integers.
constexpr SampleValue NORMALIZATION_RANGE = 1000000ULL;
// For compatibility check with the Harvester.
constexpr uint32_t DOCKYARD_VERSION = 2;
enum KoidType : SampleValue {
JOB = 100ULL,
PROCESS = 101ULL,
THREAD = 102ULL,
CHANNEL = 103ULL,
};
// A Sample.
struct Sample {
Sample(SampleTimeNs t, SampleValue v) : time(t), value(v) {}
SampleTimeNs time;
// Sample values range from [0 to SAMPLE_MAX_VALUE].
SampleValue value;
};
// Mapping between IDs and path strings.
struct PathInfo {
// The dockyard ID that corresponds to |path|, below.
DockyardId id;
// The dockyard path that corresponds to |id|, above.
std::string path;
};
// Avoid removing elements from this enum.
enum class MessageType : int64_t {
// A response to a k*Request message. Match request IDs to determine which
// request this is a response to.
kResponseOk = 0,
// The request (represented by the request ID) failed in some fundamental way.
// E.e. maybe the request never made it to the handler.
kRequestFailed = -1,
// The connection to the Harvester on Fuchsia device has broken. No further
// requests will work until a new connection is established.
kDisconnected = -2,
// The version of the Harvester is incompatible with the Dockyard.
kVersionMismatch = -3,
// Requests from the UI to the Dockyard.
kStreamSetsRequest = 1,
kDiscardSamplesRequest,
kIgnoreSamplesRequest,
kUnignoreSamplesRequest,
kConnectionRequest,
kSampleStreamsRequest,
};
std::ostream& operator<<(std::ostream& os, MessageType message_type);
// A message to or from the dockyard.
struct Message {
// The request ID normally matches a request to a response. In the case of a
// 'push' message with no request, the ID will be |NULL_REQUEST_ID|.
static constexpr uint64_t NULL_REQUEST_ID = {0u};
// Context identifier for a message. Used to match a response to a request.
// For matching against a MessageResponse::request_id.
Message(MessageType type, uint64_t id)
: message_type_(type), request_id_(id) {}
// The message type helps in routing the message. Expect to use both the
// message type and the request ID together (all current cases require both
// values).
MessageType GetMessageType() const { return message_type_; }
// Context identifier for a message. Used to match a response to a request.
uint64_t RequestId() const { return request_id_; }
protected:
// Identifier used for message routing, i.e. which code should handle this
// message.
MessageType message_type_;
// Context identifier for a message. Used to match a response to a request.
uint64_t request_id_;
};
// A message to the dockyard. The response to this message will arrive as a
// |MessageResponse| with a matching |RequestId()|.
struct MessageRequest : public Message {
MessageRequest(MessageType type) : Message(type, ++next_request_id_) {}
private:
// There is no rollover (wrap around) guard for the ID value. It's expected
// that a 64 bit integer is large enough to eliminate concern about it.
static uint64_t next_request_id_;
};
// A message from the dockyard.
struct MessageResponse : public Message {
MessageResponse()
: Message(MessageType::kResponseOk, Message::NULL_REQUEST_ID) {}
void SetMessageType(MessageType message_type) {
message_type_ = message_type;
}
bool Ok() const { return message_type_ == MessageType::kResponseOk; }
// The request ID defaults to a 'push' message with a null request ID. If this
// is a response to a specific request, set the request ID to the request's
// request ID.
void SetRequestId(uint64_t id) { request_id_ = id; }
};
// Ask that the Dockyard make a connection to a Harvester running on a Fuchsia
// device.
struct ConnectionRequest : public MessageRequest {
ConnectionRequest() : MessageRequest(MessageType::kConnectionRequest) {}
const std::string& DeviceName() const { return device_name_; }
void SetDeviceName(std::string name) { device_name_ = name; }
private:
std::string device_name_;
};
// A |ConnectionResponse| is a reply for an individual
// |ConnectionRequest|.
// See: ConnectionRequest.
struct ConnectionResponse : public MessageResponse {
ConnectionResponse(uint32_t dockyard_version, uint32_t harvester_version)
: dockyard_version_(dockyard_version),
harvester_version_(harvester_version) {}
uint32_t DockyardVersion() const { return dockyard_version_; }
uint32_t HarvesterVersion() const { return harvester_version_; }
private:
uint32_t dockyard_version_;
uint32_t harvester_version_;
};
// To delete/remove samples from a sample stream, create a DiscardSamplesRequest
// for the desired time range (by default it will remove all samples for the
// stream) and pass the struct to Dockyard::DiscardSamples().
struct DiscardSamplesRequest : public MessageRequest {
DiscardSamplesRequest()
: MessageRequest(MessageType::kDiscardSamplesRequest) {}
// Request that samples are for time range |start_time..end_time|. Defaults to
// all samples (time zero to kSampleTimeInfinite). If there is no positive
// difference between start and end, the request will not have an effect.
SampleTimeNs start_time_ns = 0;
SampleTimeNs end_time_ns = kSampleTimeInfinite;
// Each stream is identified by a Dockyard ID. Multiple streams can be
// discarded.
std::vector<DockyardId> dockyard_ids;
friend std::ostream& operator<<(std::ostream& out,
const DiscardSamplesRequest& request);
};
// A |DiscardSamplesResponse| is a reply for an individual
// |DiscardSamplesRequest|.
// See: DiscardSamplesRequest.
struct DiscardSamplesResponse : MessageResponse {
DiscardSamplesResponse() = default;
friend std::ostream& operator<<(std::ostream& out,
const DiscardSamplesResponse& response);
};
// To ignore samples, i.e. prevent them from being tracked, create a
// IgnoreSamplesRequest that will match the beginning and ending of the stream
// paths to ignore.
struct IgnoreSamplesRequest : public MessageRequest {
IgnoreSamplesRequest() : MessageRequest(MessageType::kIgnoreSamplesRequest) {}
std::string prefix;
std::string suffix;
};
// An |IgnoreSamplesResponse| is a reply for an individual
// |IgnoreSamplesRequest|.
// See: IgnoreSamplesRequest.
struct IgnoreSamplesResponse : public MessageResponse {
IgnoreSamplesResponse() = default;
};
// A stream set is a portion of a sample stream. This request allows for
// requesting multiple stream sets in a single request. The results will arrive
// in the form of a |StreamSetsResponse|.
//
// Note: Set an |OnStreamSetsCallback| with |SetStreamSetsHandler()|
// before using the request to be sure of getting the message that the
// request is complete.
//
// See: StreamSetsResponse.
struct StreamSetsRequest : public MessageRequest {
enum RenderStyle {
// When smoothing across samples, use a wider set of samples, including
// samples that are just outside of the sample set range. E.g. if the range
// is time 9 to 18, smooth over time 7 to 20.
WIDE_SMOOTHING,
// When sculpting across samples, pull the result toward the peaks and
// valleys in the data (rather than showing the average).
SCULPTING,
// For each column of the output, use the least value from the samples.
LOWEST_PER_COLUMN,
// For each column of the output, use the greatest value from the samples.
HIGHEST_PER_COLUMN,
// Add up the sample values for the slice of time and divide by the number
// of values found (i.e. take the average or mean).
AVERAGE_PER_COLUMN,
// Get the single, most recent value prior to |end_time_ns|. Generally used
// with |start_time_ns| of zero, but |start_time_ns| can still be used to
// restrict the time range.
// The |flags| NORMALIZE and SLOPE are ignored when using RECENT.
RECENT,
};
enum StreamSetsRequestFlags {
// Frame (or scale) the data set aesthetically. E.g. if the graph has little
// variance, zoom in to show that detail, rather than just having a flat
// vertical line in the graph. In some cases (like comparing graphs) this
// will be undesired. The values in the response will be in the range
// [0 to NORMALIZATION_RANGE].
NORMALIZE = 1 << 0,
// Compute the slope of the curve.
SLOPE = 1 << 1,
};
StreamSetsRequest()
: MessageRequest(MessageType::kStreamSetsRequest),
start_time_ns(0),
end_time_ns(0),
sample_count(0),
min(0),
max(0),
reserved(0),
render_style(AVERAGE_PER_COLUMN),
flags(0) {}
// Request graph data for time range |start_time..end_time| that has
// |sample_count| values for each set. If the sample stream has more or less
// samples for that time range, virtual samples will be generated based on
// available samples.
SampleTimeNs start_time_ns;
SampleTimeNs end_time_ns;
uint64_t sample_count;
SampleValue min; // Future use.
SampleValue max; // Future use.
uint64_t reserved; // Future use.
RenderStyle render_style;
uint64_t flags;
// Each stream is identified by a Dockyard ID. Multiple streams can be
// requested. Include a DockyardId for each stream of interest.
std::vector<DockyardId> dockyard_ids;
bool HasFlag(StreamSetsRequestFlags flag) const;
friend std::ostream& operator<<(std::ostream& out,
const StreamSetsRequest& request);
};
// A |StreamSetsResponse| is a reply for an individual |StreamSetsRequest|.
// See: StreamSetsRequest.
struct StreamSetsResponse : MessageResponse {
StreamSetsResponse() = default;
// The low and high all-time values for all sample streams requested. All-time
// means that these low and high points might not appear in the |data_sets|
// below. "All sample streams" means that these points may not appear in the
// same sample streams.
SampleValue lowest_value;
SampleValue highest_value;
// Each data set will correspond to a stream requested in the
// StreamSetsRequest::dockyard_ids. The value for each sample is normally in
// the range [0 to SAMPLE_MAX_VALUE]. If no value exists for the column, the
// value NO_DATA is used.
// For any DockyardId from StreamSetsRequest::dockyard_ids that isn't found,
// the resulting samples will have the value NO_STREAM.
std::vector<std::vector<SampleValue>> data_sets;
friend std::ostream& operator<<(std::ostream& out,
const StreamSetsResponse& response);
};
// This request allows for requesting multiple sample streams in a single
// request. The results will arrive in the form of a |SampleStreamsResponse|.
//
// Note: Set an |OnSampleStreamsCallback| with |SampleStreamsHandler()|
// before using the request to be sure of getting the message that the
// request is complete.
//
// See: SampleStreamsResponse.
struct SampleStreamsRequest : public MessageRequest {
SampleStreamsRequest()
: MessageRequest(MessageType::kSampleStreamsRequest),
start_time_ns(0),
end_time_ns(0) {}
SampleTimeNs start_time_ns;
SampleTimeNs end_time_ns;
// Each stream is identified by a Dockyard ID. Multiple streams can be
// requested. Include a DockyardId for each stream of interest.
std::vector<DockyardId> dockyard_ids;
friend std::ostream& operator<<(std::ostream& out,
const SampleStreamsRequest& request);
};
// A |SampleStreamsResponse| is a reply for an individual
// |SampleStreamsRequest|. See: SampleStreamsRequest.
struct SampleStreamsResponse : MessageResponse {
SampleStreamsResponse() = default;
// The low and high all-time values for all sample streams requested. All-time
// means that these low and high points might not appear in the |data_sets|
// below. "All sample streams" means that these points may not appear in the
// same sample streams.
SampleValue lowest_value;
SampleValue highest_value;
// Each data set will correspond to a stream requested in the
// SampleStreamsRequest::dockyard_ids.
std::vector<std::vector<std::pair<SampleTimeNs, SampleValue>>> data_sets;
friend std::ostream& operator<<(std::ostream& out,
const SampleStreamsResponse& response);
};
// To stop ignoring samples, create a UnignoreSamplesRequest that will match
// the |prefix| and |suffix| values from a prior IgnoreSamplesRequest.
struct UnignoreSamplesRequest : public MessageRequest {
UnignoreSamplesRequest()
: MessageRequest(MessageType::kUnignoreSamplesRequest) {}
std::string prefix;
std::string suffix;
};
// An |UnignoreSamplesResponse| is a reply for an individual
// |UnignoreSamplesRequest|.
// See: UnignoreSamplesRequest.
struct UnignoreSamplesResponse : MessageResponse {
UnignoreSamplesResponse() = default;
};
class SampleStreamMap
: public std::map<DockyardId, std::unique_ptr<SampleStream>> {
public:
// Get a reference to the sample stream for the given |dockyard_id|.
// The stream will be created if necessary.
SampleStream& StreamRef(DockyardId dockyard_id) {
return *emplace(dockyard_id, std::make_unique<SampleStream>())
.first->second;
}
};
// Lookup for a sample stream name string, given the sample stream ID.
using DockyardIdToPathMap = std::map<DockyardId, std::string>;
using DockyardPathToIdMap = std::map<std::string, DockyardId>;
// Called when a request to ignore samples is complete.
using IgnoreSamplesCallback =
std::function<void(const IgnoreSamplesRequest& request,
const IgnoreSamplesResponse& response)>;
// Called when a connection is made between the Dockyard and Harvester on a
// Fuchsia device.
using OnConnectionCallback = std::function<void(
const ConnectionRequest& request, const ConnectionResponse& response)>;
// Called when new streams are added or removed. Added values include their ID
// and string path. Removed values only have the ID.
// Intended to inform clients of PathInfoMap changes (so they may keep
// their equivalent map in sync). The racy nature of this update is not an issue
// because the rest of the API will cope with invalid stream IDs, so 'eventually
// consistent' is acceptable).
// Use SetDockyardPathsHandler() to install a StreamCallback callback.
using OnPathsCallback = std::function<void(
const std::vector<PathInfo>& add, const std::vector<DockyardId>& remove)>;
// Called after (and in response to) a request is sent to |GetStreamSets()|.
// Use SetStreamSetsHandler() to install a StreamSetsCallback callback.
using OnStreamSetsCallback = std::function<void(
const StreamSetsRequest& request, const StreamSetsResponse& response)>;
// Called after (and in response to) a request is sent to |GetSampleStreams()|.
// Use SetSampleStreamsHandler() to install a SampleStreamsCallback callback.
using OnSampleStreamsCallback =
std::function<void(const SampleStreamsRequest& request,
const SampleStreamsResponse& response)>;
// Called after (and in response to) a request is sent to |DiscardSamples()|.
using OnDiscardSamplesCallback =
std::function<void(const DiscardSamplesRequest& request,
const DiscardSamplesResponse& response)>;
class Dockyard {
public:
Dockyard();
~Dockyard();
// Insert sample information for a given dockyard_id. Not intended for use by
// the GUI.
void AddSample(DockyardId dockyard_id, Sample sample);
// Insert sample information for a given dockyard_id. Not intended for use by
// the GUI.
void AddSamples(DockyardId dockyard_id, const std::vector<Sample>& samples);
// The *approximate* difference between host time and device time. This value
// is negotiated at connection time and not reevaluated. If either clock is
// altered this value may be wildly inaccurate. The intended use of this value
// is to hint the GUI when displaying sample times (not for doing CI analysis
// or similar computations).
// If the value is positive then the device clock is ahead of the host clock.
// Given a sample, subtract this value to get the host time.
// Given a host time, add this value to get device (sample) time.
// See: LatestSampleTimeNs()
SampleTimeNs DeviceDeltaTimeNs() const;
// Helper functions to compute time. Read important details in the description
// of |DeviceDeltaTimeNs|.
SampleTimeNs DeviceTimeToHostTime(SampleTimeNs device_time_ns) const {
return device_time_ns - device_time_delta_ns_;
}
SampleTimeNs HostTimeToDeviceTime(SampleTimeNs host_time_ns) const {
return host_time_ns + device_time_delta_ns_;
}
// Discard the stream data. The path/ID lookup will remain intact after the
// discard (i.e. MatchPaths() will still find the paths).
void DiscardSamples(DiscardSamplesRequest&& request,
OnDiscardSamplesCallback callback);
// Set the difference in clocks between the host machine and the Fuchsia
// device, in nanoseconds.
void SetDeviceTimeDeltaNs(SampleTimeNs delta_ns);
// The time stamp for the most recent batch of samples to arrive. The time is
// device time (not host time) in nanoseconds.
// See: DeviceDeltaTimeNs()
SampleTimeNs LatestSampleTimeNs() const;
// Get Dockyard identifier for a given path. The ID values are stable
// throughout execution, so they may be cached.
//
// Returns a Dockyard ID that corresponds to |dockyard_path|.
DockyardId GetDockyardId(const std::string& dockyard_path);
// Determine whether |dockyard_path| is valid (if it exists).
bool HasDockyardPath(const std::string& dockyard_path,
DockyardId* dockyard_id) const;
// Translate a |dockyard_id| to a |dockyard_path|. |dockyard_path| is an out
// value. Returns false if |dockyard_id| is unknown.
bool GetDockyardPath(DockyardId dockyard_id,
std::string* dockyard_path) const;
// Search the existing paths for those that start with |starting| and end with
// |ending|. This is similar to having a single '*' wildcard search, something
// akin to find all "$starting*$ending".
// Returns a map of paths to IDs that is a subset of (or equal to) all known
// stream sets.
DockyardPathToIdMap MatchPaths(const std::string& starting,
const std::string& ending) const;
// Request graph data for time range |start_time..end_time| that has
// |sample_count| values for each set. If the sample stream has more or less
// samples for that time range, virtual samples will be generated based on
// available samples.
//
// The results will be supplied in a call to the |callback|.
void GetStreamSets(StreamSetsRequest&& request,
OnStreamSetsCallback callback);
// Request sample stream data for time range |start_time..end_time|.
//
// The results will be supplied in a call to the |callback|.
void GetSampleStreams(SampleStreamsRequest&& request,
OnSampleStreamsCallback callback);
// Ignore subsequent samples per |request|. Note that existing (prior) samples
// are not removed/discarded. To remove samples see: DiscardSamples().
void IgnoreSamples(IgnoreSamplesRequest&& request,
IgnoreSamplesCallback callback);
// Called by server when a connection is made.
void OnConnection(MessageType message_type, uint32_t harvester_version);
// Start collecting data from a named device. Tip: device names are normally
// four short words, such as "duck-floor-quick-rock". If |StartCollectingFrom|
// was previously called, call |StopCollectingFromDevice| before starting a
// new connection (otherwise this call will fail and return false).
// Returns true if successful.
bool StartCollectingFrom(ConnectionRequest&& request,
OnConnectionCallback callback);
// The inverse of |StartCollectingFrom|. It's safe to call this regardless of
// whether |StartCollectingFrom| succeeded (no work is done unless
// |StartCollectingFrom| had succeeded).
void StopCollectingFromDevice();
// Sets the function called when sample streams are added or removed. Pass
// nullptr as |callback| to stop receiving calls.
//
// Returns prior callback or nullptr.
OnPathsCallback SetDockyardPathsHandler(OnPathsCallback callback);
// Generate responses and call handlers for sample requests. Not intended for
// use by the GUI.
void ProcessRequests();
// Clear out the samples and other data that has been collected by the
// harvester. This is not normally used unless the host wishes to reset the
// data when a new connection is made.
void ResetHarvesterData();
// Write a snapshot of the current dockyard state to a string. Note that this
// could be rather large. As the name implies it's intended for debugging
// only.
std::ostringstream DebugDump() const;
private:
// TODO(fxb/38): avoid having a global mutex. Use a queue to update
// data.
mutable std::mutex mutex_;
std::thread server_thread_;
// The server handles grpc messages (runs in a background thread).
std::unique_ptr<grpc::Server> grpc_server_;
// The service handles proto buffers. The |service_| must remain valid until
// the |server_| (which holds a weak pointer to |service_|) is finished.
std::unique_ptr<DockyardServiceImpl> protocol_buffer_service_;
// The time (clock) on the device will likely differ from the host.
SampleTimeNs device_time_delta_ns_;
SampleTimeNs latest_sample_time_ns_;
// Communication with the GUI.
ConnectionRequest on_connection_request_;
OnConnectionCallback on_connection_handler_;
OnPathsCallback on_paths_handler_;
std::vector<std::pair<DiscardSamplesRequest, OnDiscardSamplesCallback>>
pending_discard_requests_owned_;
std::vector<std::pair<SampleStreamsRequest, OnSampleStreamsCallback>>
pending_raw_get_requests_owned_;
std::vector<std::pair<StreamSetsRequest, OnStreamSetsCallback>>
pending_get_requests_owned_;
std::vector<std::pair<IgnoreSamplesRequest, IgnoreSamplesCallback>>
pending_ignore_samples_owned_;
// Storage of sample data.
SampleStreamMap sample_streams_;
std::map<DockyardId, std::pair<SampleValue, SampleValue>>
sample_stream_low_high_;
// Track the ignore requests that have been made so that future paths that
// match the ignore list can be added to the ignore_dockyard_ids_.
std::set<std::pair<std::string, std::string>> ignore_streams_;
// Ignore list derived from |ignore_streams_|. This is an optimization over
// checking each update against the ignore_streams_. Doing a set lookup is
// much less expensive.
std::set<DockyardId> ignore_dockyard_ids_;
// Dockyard path <--> ID look up.
DockyardPathToIdMap dockyard_path_to_id_;
DockyardIdToPathMap dockyard_id_to_path_;
// Each of these Compute*() methods aggregate samples in different ways.
// There's no single 'true' way to represent aggregated data, so the choice
// is left to the caller. Which of these is used depends on the
// |StreamSetsRequestFlags| in the |StreamSetsRequest.flags| field.
void ComputeAveragePerColumn(DockyardId dockyard_id,
const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
void ComputeHighestPerColumn(DockyardId dockyard_id,
const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
void ComputeLowestPerColumn(DockyardId dockyard_id,
const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
void ComputeRecent(DockyardId dockyard_id, const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
void ComputeSculpted(DockyardId dockyard_id,
const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
void ComputeSmoothed(DockyardId dockyard_id,
const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
void ComputeLowestHighestForRequest(const StreamSetsRequest& request,
StreamSetsResponse* response) const;
void ComputeLowestHighestForSampleStreamsRequest(
const SampleStreamsRequest& request,
SampleStreamsResponse* response) const;
// A private version of GetDockyardId that expects that a |mutex_| lock has
// already been acquired.
DockyardId GetDockyardIdLocked(const std::string& dockyard_path);
// Ignore all further stream set data received that matches the patterns.
// Existing samples are not removed by this call. This call expects that a
// lock on |mutex_| has already been acquired.
void IgnoreSamplesLocked(const std::string& starting,
const std::string& ending);
// Listen for incoming samples.
//
// Returns |false| on problems with starting the gRPC server.
bool Initialize();
// A private version of MatchPaths that expects that a lock has already been
// acquired.
DockyardPathToIdMap MatchPathsLocked(const std::string& starting,
const std::string& ending) const;
// Rework the response so that all values are in the range 0 to one million.
// This represents a 0.0 to 1.0 value, scaled up.
void NormalizeResponse(DockyardId dockyard_id,
const SampleStream& sample_stream,
const StreamSetsRequest& request,
std::vector<SampleValue>* samples) const;
// The average of the lowest and highest value in the stream.
SampleValue OverallAverageForStream(DockyardId dockyard_id) const;
// Processes the requests entered by DiscardSamples().
void ProcessDiscardSamples(const DiscardSamplesRequest& request,
DiscardSamplesResponse* response);
// Process a request to ignore samples.
void ProcessIgnoreSamples(const IgnoreSamplesRequest& request,
IgnoreSamplesResponse* response);
// Gather the overall lowest and highest values encountered.
void ProcessSingleRequest(const StreamSetsRequest& request,
StreamSetsResponse* response) const;
// Process a single request for sample streams.
void ProcessSingleSampleStreamsRequest(const SampleStreamsRequest& request,
SampleStreamsResponse* response) const;
// Listen for Harvester connections from the Fuchsia device.
void RunGrpcServer();
friend class ::SystemMonitorDockyardHostTest;
friend class ::dockyard::SystemMonitorDockyardTest;
friend std::ostream& operator<<(std::ostream& out, const Dockyard& dockyard);
};
// Merge and print a request and response. It can make debugging easier to have
// the data correlated.
std::ostringstream DebugPrintQuery(const Dockyard& dockyard,
const StreamSetsRequest& request,
const StreamSetsResponse& response);
} // namespace dockyard
#endif // SRC_DEVELOPER_SYSTEM_MONITOR_LIB_DOCKYARD_DOCKYARD_H_