1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <trace-provider/handler.h>
8 
9 #include <lib/async/cpp/wait.h>
10 #include <lib/zx/fifo.h>
11 #include <lib/zx/vmo.h>
12 #include <fbl/intrusive_hash_table.h>
13 #include <fbl/macros.h>
14 #include <fbl/string.h>
15 #include <fbl/unique_ptr.h>
16 #include <fbl/vector.h>
17 #include <lib/zircon-internal/fnv1hash.h>
18 
19 namespace trace {
20 namespace internal {
21 
22 class Session final : public trace::TraceHandler {
23 public:
24     static void StartEngine(async_dispatcher_t* dispatcher,
25                             trace_buffering_mode_t buffering_mode,
26                             zx::vmo buffer, zx::fifo fifo,
27                             fbl::Vector<fbl::String> enabled_categories);
28     static void StopEngine();
29 
30 private:
31     Session(void* buffer, size_t buffer_num_bytes, zx::fifo fifo,
32                      fbl::Vector<fbl::String> enabled_categories);
33     ~Session() override;
34 
35     // |trace::TraceHandler|
36     bool IsCategoryEnabled(const char* category) override;
37     void TraceStarted() override;
38     void TraceStopped(async_dispatcher_t* dispatcher,
39                       zx_status_t disposition, size_t buffer_bytes_written) override;
40     // This is called in streaming mode to notify the trace manager that
41     // buffer |buffer_number| is full and needs to be saved.
42     void NotifyBufferFull(uint32_t wrapped_count, uint64_t durable_data_end)
43         override;
44 
45     void HandleFifo(async_dispatcher_t* dispatcher, async::WaitBase* wait,
46                     zx_status_t status,
47                     const zx_packet_signal_t* signal);
48     bool ReadFifoMessage();
49 
50     // This is called in streaming mode when TraceManager reports back that
51     // it has saved the buffer.
52     static zx_status_t MarkBufferSaved(uint32_t wrapped_count,
53                                        uint64_t durable_data_end);
54 
55     void* buffer_;
56     size_t buffer_num_bytes_;
57     zx::fifo fifo_;
58     async::WaitMethod<Session, &Session::HandleFifo> fifo_wait_;
59     fbl::Vector<fbl::String> const enabled_categories_;
60 
61     using CString = const char*;
62 
63     // For faster implementation of IsCategoryEnabled().
64     struct StringSetEntry : public fbl::SinglyLinkedListable<
65             fbl::unique_ptr<StringSetEntry>> {
StringSetEntryStringSetEntry66         StringSetEntry(const CString& string)
67             : string(string) {}
68 
69         const CString string;
70 
71         // Used by the hash table.
GetHashStringSetEntry72         static size_t GetHash(CString key) {
73             return fnv1a64str(key);
74         }
75     };
76 
77     // We want to work with C strings here, but the default implementation
78     // would just compare pointers.
79     struct CategoryStringKeyTraits {
GetKeyCategoryStringKeyTraits80         static CString GetKey(const StringSetEntry& obj) {
81             return obj.string;
82         }
EqualToCategoryStringKeyTraits83         static bool EqualTo(const CString& key1, const CString& key2) {
84             return strcmp(key1, key2) == 0;
85         }
86     };
87 
88     using StringSet = fbl::HashTable<const char*,
89         fbl::unique_ptr<StringSetEntry>,
90         fbl::SinglyLinkedList<fbl::unique_ptr<StringSetEntry>>, // default
91         size_t, // default
92         37, // default
93         CategoryStringKeyTraits>;
94     StringSet enabled_category_set_;
95 
96     DISALLOW_COPY_ASSIGN_AND_MOVE(Session);
97 };
98 
99 } // namespace internal
100 } // namespace trace
101