OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/log.h" | 5 #include "vm/log.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
9 #include "vm/thread.h" | 9 #include "vm/thread.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages."); | 13 DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages."); |
14 | 14 |
15 DEFINE_FLAG(charp, | 15 DEFINE_FLAG(charp, |
16 isolate_log_filter, | 16 isolate_log_filter, |
17 NULL, | 17 NULL, |
18 "Log isolates whose name include the filter. " | 18 "Log isolates whose name include the filter. " |
19 "Default: service isolate log messages are suppressed " | 19 "Default: service isolate log messages are suppressed " |
20 "(specify 'vm-service' to log them)."); | 20 "(specify 'vm-service' to log them)."); |
21 | 21 |
22 Log::Log(LogPrinter printer) | 22 Log::Log(LogPrinter printer) |
23 : printer_(printer), manual_flush_(0), buffer_(0) {} | 23 : printer_(printer), manual_flush_(0), buffer_(0) {} |
24 | 24 |
25 | |
26 Log::~Log() { | 25 Log::~Log() { |
27 // Did someone enable manual flushing and then forgot to Flush? | 26 // Did someone enable manual flushing and then forgot to Flush? |
28 ASSERT(cursor() == 0); | 27 ASSERT(cursor() == 0); |
29 } | 28 } |
30 | 29 |
31 | |
32 Log* Log::Current() { | 30 Log* Log::Current() { |
33 Thread* thread = Thread::Current(); | 31 Thread* thread = Thread::Current(); |
34 if (thread == NULL) { | 32 if (thread == NULL) { |
35 OSThread* os_thread = OSThread::Current(); | 33 OSThread* os_thread = OSThread::Current(); |
36 ASSERT(os_thread != NULL); | 34 ASSERT(os_thread != NULL); |
37 return os_thread->log(); | 35 return os_thread->log(); |
38 } | 36 } |
39 Isolate* isolate = thread->isolate(); | 37 Isolate* isolate = thread->isolate(); |
40 if (isolate != NULL && Log::ShouldLogForIsolate(isolate)) { | 38 if (isolate != NULL && Log::ShouldLogForIsolate(isolate)) { |
41 OSThread* os_thread = thread->os_thread(); | 39 OSThread* os_thread = thread->os_thread(); |
42 ASSERT(os_thread != NULL); | 40 ASSERT(os_thread != NULL); |
43 return os_thread->log(); | 41 return os_thread->log(); |
44 } else { | 42 } else { |
45 return Log::NoOpLog(); | 43 return Log::NoOpLog(); |
46 } | 44 } |
47 } | 45 } |
48 | 46 |
49 | |
50 void Log::Print(const char* format, ...) { | 47 void Log::Print(const char* format, ...) { |
51 if (this == NoOpLog()) { | 48 if (this == NoOpLog()) { |
52 return; | 49 return; |
53 } | 50 } |
54 | 51 |
55 va_list args; | 52 va_list args; |
56 va_start(args, format); | 53 va_start(args, format); |
57 VPrint(format, args); | 54 VPrint(format, args); |
58 va_end(args); | 55 va_end(args); |
59 } | 56 } |
60 | 57 |
61 | |
62 void Log::VPrint(const char* format, va_list args) { | 58 void Log::VPrint(const char* format, va_list args) { |
63 if (this == NoOpLog()) { | 59 if (this == NoOpLog()) { |
64 return; | 60 return; |
65 } | 61 } |
66 | 62 |
67 // Measure. | 63 // Measure. |
68 va_list measure_args; | 64 va_list measure_args; |
69 va_copy(measure_args, args); | 65 va_copy(measure_args, args); |
70 intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args); | 66 intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args); |
71 va_end(measure_args); | 67 va_end(measure_args); |
(...skipping 10 matching lines...) Expand all Loading... |
82 for (intptr_t i = 0; i < len; i++) { | 78 for (intptr_t i = 0; i < len; i++) { |
83 buffer_.Add(buffer[i]); | 79 buffer_.Add(buffer[i]); |
84 } | 80 } |
85 free(buffer); | 81 free(buffer); |
86 | 82 |
87 if ((manual_flush_ == 0) || FLAG_force_log_flush) { | 83 if ((manual_flush_ == 0) || FLAG_force_log_flush) { |
88 Flush(); | 84 Flush(); |
89 } | 85 } |
90 } | 86 } |
91 | 87 |
92 | |
93 void Log::Flush(const intptr_t cursor) { | 88 void Log::Flush(const intptr_t cursor) { |
94 if (this == NoOpLog()) { | 89 if (this == NoOpLog()) { |
95 return; | 90 return; |
96 } | 91 } |
97 if (buffer_.is_empty()) { | 92 if (buffer_.is_empty()) { |
98 return; | 93 return; |
99 } | 94 } |
100 if (buffer_.length() <= cursor) { | 95 if (buffer_.length() <= cursor) { |
101 return; | 96 return; |
102 } | 97 } |
103 TerminateString(); | 98 TerminateString(); |
104 const char* str = &buffer_[cursor]; | 99 const char* str = &buffer_[cursor]; |
105 ASSERT(str != NULL); | 100 ASSERT(str != NULL); |
106 printer_("%s", str); | 101 printer_("%s", str); |
107 buffer_.TruncateTo(cursor); | 102 buffer_.TruncateTo(cursor); |
108 } | 103 } |
109 | 104 |
110 | |
111 void Log::Clear() { | 105 void Log::Clear() { |
112 if (this == NoOpLog()) { | 106 if (this == NoOpLog()) { |
113 return; | 107 return; |
114 } | 108 } |
115 buffer_.TruncateTo(0); | 109 buffer_.TruncateTo(0); |
116 } | 110 } |
117 | 111 |
118 | |
119 intptr_t Log::cursor() const { | 112 intptr_t Log::cursor() const { |
120 return buffer_.length(); | 113 return buffer_.length(); |
121 } | 114 } |
122 | 115 |
123 | |
124 bool Log::ShouldLogForIsolate(const Isolate* isolate) { | 116 bool Log::ShouldLogForIsolate(const Isolate* isolate) { |
125 if (FLAG_isolate_log_filter == NULL) { | 117 if (FLAG_isolate_log_filter == NULL) { |
126 if (isolate->is_service_isolate()) { | 118 if (isolate->is_service_isolate()) { |
127 // By default, do not log for the service isolate. | 119 // By default, do not log for the service isolate. |
128 return false; | 120 return false; |
129 } | 121 } |
130 return true; | 122 return true; |
131 } | 123 } |
132 const char* name = isolate->name(); | 124 const char* name = isolate->name(); |
133 ASSERT(name != NULL); | 125 ASSERT(name != NULL); |
134 if (strstr(name, FLAG_isolate_log_filter) == NULL) { | 126 if (strstr(name, FLAG_isolate_log_filter) == NULL) { |
135 // Filter does not match, do not log for this isolate. | 127 // Filter does not match, do not log for this isolate. |
136 return false; | 128 return false; |
137 } | 129 } |
138 return true; | 130 return true; |
139 } | 131 } |
140 | 132 |
141 | |
142 Log Log::noop_log_; | 133 Log Log::noop_log_; |
143 Log* Log::NoOpLog() { | 134 Log* Log::NoOpLog() { |
144 return &noop_log_; | 135 return &noop_log_; |
145 } | 136 } |
146 | 137 |
147 | |
148 void Log::TerminateString() { | 138 void Log::TerminateString() { |
149 if (this == NoOpLog()) { | 139 if (this == NoOpLog()) { |
150 return; | 140 return; |
151 } | 141 } |
152 buffer_.Add('\0'); | 142 buffer_.Add('\0'); |
153 } | 143 } |
154 | 144 |
155 | |
156 void Log::EnableManualFlush() { | 145 void Log::EnableManualFlush() { |
157 if (this == NoOpLog()) { | 146 if (this == NoOpLog()) { |
158 return; | 147 return; |
159 } | 148 } |
160 manual_flush_++; | 149 manual_flush_++; |
161 } | 150 } |
162 | 151 |
163 | |
164 void Log::DisableManualFlush() { | 152 void Log::DisableManualFlush() { |
165 if (this == NoOpLog()) { | 153 if (this == NoOpLog()) { |
166 return; | 154 return; |
167 } | 155 } |
168 | 156 |
169 manual_flush_--; | 157 manual_flush_--; |
170 ASSERT(manual_flush_ >= 0); | 158 ASSERT(manual_flush_ >= 0); |
171 if (manual_flush_ == 0) { | 159 if (manual_flush_ == 0) { |
172 Flush(); | 160 Flush(); |
173 } | 161 } |
174 } | 162 } |
175 | 163 |
176 | |
177 void LogBlock::Initialize() { | 164 void LogBlock::Initialize() { |
178 log_->EnableManualFlush(); | 165 log_->EnableManualFlush(); |
179 } | 166 } |
180 | 167 |
181 | |
182 LogBlock::~LogBlock() { | 168 LogBlock::~LogBlock() { |
183 log_->Flush(cursor_); | 169 log_->Flush(cursor_); |
184 log_->DisableManualFlush(); | 170 log_->DisableManualFlush(); |
185 } | 171 } |
186 | 172 |
187 } // namespace dart | 173 } // namespace dart |
OLD | NEW |