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