1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // This file declares the trace::agent_logger::LoggerApp class which implements
16 : // a simple logging service for binding to RPC.
17 :
18 : #ifndef SYZYGY_TRACE_AGENT_LOGGER_AGENT_LOGGER_APP_H_
19 : #define SYZYGY_TRACE_AGENT_LOGGER_AGENT_LOGGER_APP_H_
20 :
21 : #include "base/command_line.h"
22 : #include "base/files/file_path.h"
23 : #include "base/strings/string_piece.h"
24 : #include "base/strings/string_util.h"
25 : #include "base/time/time.h"
26 : #include "syzygy/application/application.h"
27 :
28 m : namespace trace {
29 m : namespace agent_logger {
30 :
31 : // Encapsulates a Logger as a command-line application.
32 : //
33 : // The application runs as a singleton for a given instance id. This is
34 : // enforced using a named mutex, specialized by the instance id, that the
35 : // logger acquires on startup. If the mutex is already held by another
36 : // process (presumably another logger instance) then the logger aborts.
37 : //
38 : // The logger also exposes two named events which are set on logger startup
39 : // and shutdown, respectively. The spawn command waits for the startup event
40 : // to be set (or the termination of the spawned logger) before returning and
41 : // the stop command waits for the shutdown event to be set before returning.
42 m : class LoggerApp : public application::AppImplBase {
43 m : public:
44 m : LoggerApp();
45 m : ~LoggerApp();
46 :
47 m : static const size_t kMaxInstanceIdLength = 16;
48 :
49 : // @name Implementation of the AppImplBase interface.
50 : // @{
51 m : bool ParseCommandLine(const base::CommandLine* command_line);
52 m : int Run();
53 : // @}
54 :
55 : // Public for unit-testing purposes.
56 : // @{
57 : // Start the logger in the foreground. Running app_command_line_ if it is
58 : // not empty.
59 m : bool Start();
60 : // Start the logger in the background.
61 m : bool Spawn();
62 : // Print the status (running/not-running) of the logger.
63 m : bool Status();
64 : // Stop a (separately running) logger instance.
65 m : bool Stop();
66 : // @}
67 :
68 m : protected:
69 : // The type of function to which action keywords are mapped.
70 m : typedef bool (LoggerApp::*ActionHandler)();
71 :
72 : // A structure to hold a mapping between an action and its implementation.
73 m : struct ActionTableEntry {
74 m : const wchar_t* const action;
75 m : const ActionHandler handler;
76 m : };
77 :
78 : // A functor to allow searching (and sorting validation) of a table of
79 : // ActionTableEntry items.
80 m : struct ActionTableEntryCompare {
81 m : bool operator()(const ActionTableEntry& lhs,
82 m : const ActionTableEntry& rhs) const {
83 m : return ::_wcsicmp(lhs.action, rhs.action) < 0;
84 m : }
85 :
86 m : bool operator()(const base::StringPiece16& lhs,
87 m : const ActionTableEntry& rhs) const {
88 m : return ::_wcsnicmp(lhs.data(), rhs.action, lhs.size()) < 0;
89 m : }
90 :
91 m : bool operator()(const ActionTableEntry& lhs,
92 m : const base::StringPiece16& rhs) const {
93 m : return ::_wcsnicmp(lhs.action, rhs.data(), rhs.size()) < 0;
94 m : }
95 m : };
96 :
97 : // A helper function to find the handler method for a given action.
98 m : static const ActionTableEntry* FindActionHandler(
99 m : const base::StringPiece16& action);
100 :
101 : // Helper to resolve output_file_path_ to an open file. This will set
102 : // @p must_close to true if @path denotes a newly opened file, and false
103 : // if it denotes stderr or stdout.
104 m : bool OpenOutputFile(FILE** output_file, bool* must_close);
105 :
106 : // Print the usage/help text, plus an optional @p message.
107 m : bool Usage(const base::CommandLine* command_line,
108 m : const base::StringPiece& message) const;
109 :
110 : // A table mapping action keywords to their handler implementations.
111 m : static const ActionTableEntry kActionTable[];
112 :
113 : // Command-line actions.
114 : // @{
115 m : static const wchar_t kStart[];
116 m : static const wchar_t kSpawn[];
117 m : static const wchar_t kStatus[];
118 m : static const wchar_t kStop[];
119 : // @}
120 :
121 : // Command-line options.
122 : // @{
123 m : static const char kInstanceId[];
124 m : static const char kUniqueInstanceId[];
125 m : static const char kOutputFile[];
126 m : static const char kAppend[];
127 m : static const char kMiniDumpDir[];
128 : // @}
129 :
130 : // Special-case output file value tokens.
131 : // @{
132 m : static const wchar_t kStdOut[];
133 m : static const wchar_t kStdErr[];
134 : // @}
135 :
136 : // The command line parameters pertaining to the logger.
137 m : base::CommandLine logger_command_line_;
138 :
139 : // The command-line parameters pertaining to the subprocess to exec.
140 m : std::unique_ptr<base::CommandLine> app_command_line_;
141 :
142 : // Members to hold the logger's parsed command-line parameters
143 : // @{
144 m : std::wstring instance_id_;
145 m : std::wstring action_;
146 m : ActionHandler action_handler_;
147 m : base::FilePath output_file_path_;
148 m : base::FilePath mini_dump_dir_;
149 m : bool append_;
150 : // @}
151 :
152 m : private:
153 m : DISALLOW_COPY_AND_ASSIGN(LoggerApp);
154 m : };
155 :
156 m : } // namespace agent_logger
157 m : } // namespace trace
158 :
159 : #endif // SYZYGY_TRACE_AGENT_LOGGER_AGENT_LOGGER_APP_H_
|