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::logger::LoggerApp class which implements
16 : // a simple logging service for binding to RPC.
17 :
18 : #ifndef SYZYGY_TRACE_LOGGER_LOGGER_APP_H_
19 : #define SYZYGY_TRACE_LOGGER_LOGGER_APP_H_
20 :
21 : #include "base/basictypes.h"
22 : #include "base/command_line.h"
23 : #include "base/file_path.h"
24 : #include "base/string_piece.h"
25 : #include "base/string_util.h"
26 : #include "base/time.h"
27 : #include "syzygy/common/application.h"
28 :
29 : namespace trace {
30 : namespace 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 : class LoggerApp : public common::AppImplBase {
44 : public:
45 : LoggerApp();
46 : ~LoggerApp();
47 :
48 : // @name Implementation of the AppImplBase interface.
49 : // @{
50 : bool ParseCommandLine(const CommandLine* command_line);
51 : int Run();
52 : // @}
53 :
54 : // Public for unit-testing purposes.
55 : // @{
56 : // Start the logger in the foreground. Running app_command_line_ if it is
57 : // not empty.
58 : bool Start();
59 : // Start the logger in the background.
60 : bool Spawn();
61 : // Print the status (running/not-running) of the logger.
62 : bool Status();
63 : // Stop a (separately running) logger instance.
64 : bool Stop();
65 : // @}
66 :
67 : protected:
68 : // The type of function to which action keywords are mapped.
69 : typedef bool (LoggerApp::*ActionHandler)();
70 :
71 : // A structure to hold a mapping between an action and its implementation.
72 : struct ActionTableEntry {
73 : const wchar_t* const action;
74 : const ActionHandler handler;
75 : };
76 :
77 : // A functor to allow searching (and sorting validation) of a table of
78 : // ActionTableEntry items.
79 : struct ActionTableEntryCompare {
80 : bool operator()(const ActionTableEntry& lhs,
81 E : const ActionTableEntry& rhs) const {
82 E : return ::_wcsicmp(lhs.action, rhs.action) < 0;
83 E : }
84 :
85 : bool operator()(const base::StringPiece16& lhs,
86 : const ActionTableEntry& rhs) const {
87 : return ::_wcsnicmp(lhs.data(), rhs.action, lhs.size()) < 0;
88 : }
89 :
90 : bool operator()(const ActionTableEntry& lhs,
91 E : const base::StringPiece16& rhs) const {
92 E : return ::_wcsnicmp(lhs.action, rhs.data(), rhs.size()) < 0;
93 E : }
94 : };
95 :
96 : // A helper function to find the handler method for a given action.
97 : static const ActionTableEntry* FindActionHandler(
98 : const base::StringPiece16& action);
99 :
100 : // Helper to resolve output_file_path_ to an open file. This will set
101 : // @p must_close to true if @path denotes a newly opened file, and false
102 : // if it denotes stderr or stdout.
103 : bool OpenOutputFile(FILE** output_file, bool* must_close);
104 :
105 : // Print the usage/help text, plus an optional @p message.
106 : bool Usage(const CommandLine* command_line,
107 : const base::StringPiece& message) const;
108 :
109 : // A table mapping action keywords to their handler implementations.
110 : static const ActionTableEntry kActionTable[];
111 :
112 : // Command-line actions.
113 : // @{
114 : static const wchar_t kStart[];
115 : static const wchar_t kSpawn[];
116 : static const wchar_t kStatus[];
117 : static const wchar_t kStop[];
118 : // @}
119 :
120 : // Command-line options.
121 : // @{
122 : static const char kInstanceId[];
123 : static const char kOutputFile[];
124 : static const char kAppend[];
125 : // @}
126 :
127 : // Special-case output-file tokens.
128 : // @{
129 : static const wchar_t kStdOut[];
130 : static const wchar_t kStdErr[];
131 : // @}
132 :
133 : // The command line parameters pertaining to the logger.
134 : CommandLine logger_command_line_;
135 :
136 : // The command-line parameters pertaining to the subprocess to exec.
137 : scoped_ptr<CommandLine> app_command_line_;
138 :
139 : // Members to hold the logger's parsed command-line parameters
140 : // @{
141 : std::wstring instance_id_;
142 : std::wstring action_;
143 : ActionHandler action_handler_;
144 : FilePath output_file_path_;
145 : bool append_;
146 : // @}
147 :
148 : private:
149 : DISALLOW_COPY_AND_ASSIGN(LoggerApp);
150 : };
151 :
152 : } // namespace logger
153 : } // namespace trace
154 :
155 : #endif // SYZYGY_TRACE_LOGGER_LOGGER_APP_H_
|