Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(829)

Side by Side Diff: src/log-utils.cc

Issue 115814: Implement a dynamically growing memory log buffer with an upper limit. (Closed)
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "log-utils.h"
31
32 namespace v8 {
33 namespace internal {
34
35 #ifdef ENABLE_LOGGING_AND_PROFILING
36
37 LogDynamicBuffer::LogDynamicBuffer(int block_size, int max_size)
38 : block_size_(block_size),
39 max_size_(max_size - (max_size % block_size_)),
40 blocks_(max_size_ / block_size_ + 1),
41 write_pos_(0), block_index_(0), block_write_pos_(0) {
42 ASSERT(BlocksCount() > 0);
43 blocks_[0] = NewArray<char>(block_size_);
Søren Thygesen Gjesse 2009/05/27 12:00:40 Maybe add a private method AllocateBlock.
Mikhail Naganov 2009/05/28 07:05:35 Done.
44 for (int i = 1; i < BlocksCount(); ++i) {
45 blocks_[i] = NULL;
46 }
47 }
48
49
50 LogDynamicBuffer::~LogDynamicBuffer() {
51 for (int i = 0; i < BlocksCount(); ++i) {
52 DeleteArray(blocks_[i]);
53 }
54 }
55
56
57 int LogDynamicBuffer::Read(int from_pos, char* dest_buf, int buf_size) {
58 if (buf_size == 0) return 0;
59 int read_pos = from_pos;
60 int block_read_index = BlockIndex(from_pos);
61 int block_read_pos = PosInBlock(from_pos);
62 int dest_buf_pos = 0;
63 // Read until dest_buf is filled, or write_pos_ encountered.
64 while (read_pos < write_pos_ && dest_buf_pos < buf_size) {
65 const int read_size = Min(write_pos_ - read_pos,
66 Min(buf_size - dest_buf_pos, block_size_ - block_read_pos));
67 memcpy(dest_buf + dest_buf_pos,
68 blocks_[block_read_index] + block_read_pos, read_size);
69 block_read_pos += read_size;
70 dest_buf_pos += read_size;
71 read_pos += read_size;
72 if (block_read_pos == block_size_) {
73 block_read_pos = 0;
74 ++block_read_index;
75 }
76 }
77 return dest_buf_pos;
78 }
79
80
81 int LogDynamicBuffer::Write(const char* data, int data_size) {
82 if ((write_pos_ + data_size) > max_size_) return 0;
83 int data_pos = 0;
84 while (data_pos < data_size) {
85 const int write_size =
86 Min(data_size - data_pos, block_size_ - block_write_pos_);
87 memcpy(blocks_[block_index_] + block_write_pos_, data + data_pos,
88 write_size);
89 block_write_pos_ += write_size;
90 data_pos += write_size;
91 if (block_write_pos_ == block_size_) {
92 block_write_pos_ = 0;
93 blocks_[++block_index_] = NewArray<char>(block_size_);
Søren Thygesen Gjesse 2009/05/27 12:00:40 Ditto.
Mikhail Naganov 2009/05/28 07:05:35 Done.
94 }
95 }
96 write_pos_ += data_size;
97 return data_size;
98 }
99
100
101 Log::WritePtr Log::Write = NULL;
102 FILE* Log::output_handle_ = NULL;
103 LogDynamicBuffer* Log::output_buffer_ = NULL;
104 Mutex* Log::mutex_ = NULL;
105 char* Log::message_buffer_ = NULL;
106
107
108 void Log::Init() {
109 mutex_ = OS::CreateMutex();
110 message_buffer_ = NewArray<char>(kMessageBufferSize);
111 }
112
113
114 void Log::OpenStdout() {
115 ASSERT(!IsEnabled());
116 output_handle_ = stdout;
117 Write = WriteToFile;
118 Init();
119 }
120
121
122 void Log::OpenFile(const char* name) {
123 ASSERT(!IsEnabled());
124 output_handle_ = OS::FOpen(name, OS::LogFileOpenMode);
125 Write = WriteToFile;
126 Init();
127 }
128
129
130 void Log::OpenMemoryBuffer() {
131 ASSERT(!IsEnabled());
132 output_buffer_ = new LogDynamicBuffer(
133 kDynamicBufferBlockSize, kMaxDynamicBufferSize);
134 Write = WriteToMemory;
135 Init();
136 }
137
138
139 void Log::Close() {
140 if (Write == WriteToFile) {
141 fclose(output_handle_);
142 output_handle_ = NULL;
143 } else if (Write == WriteToMemory) {
144 delete output_buffer_;
145 output_buffer_ = NULL;
146 } else {
147 ASSERT(Write == NULL);
148 }
149 Write = NULL;
150
151 delete mutex_;
152 mutex_ = NULL;
153 }
154
155
156 int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) {
157 if (Write != WriteToMemory) return 0;
158 ASSERT(output_buffer_ != NULL);
159 ASSERT(from_pos >= 0);
160 ASSERT(max_size >= 0);
161 int actual_size = output_buffer_->Read(from_pos, dest_buf, max_size);
162 ASSERT(actual_size <= max_size);
163 if (actual_size == 0) return 0;
164
165 // Find previous log line boundary.
166 char* end_pos = dest_buf + actual_size - 1;
167 while (end_pos >= dest_buf && *end_pos != '\n') --end_pos;
168 actual_size = end_pos - dest_buf + 1;
169 ASSERT(actual_size <= max_size);
170 return actual_size;
171 }
172
173
174 LogMessageBuilder::LogMessageBuilder(): sl(Log::mutex_), pos_(0) {
175 ASSERT(Log::message_buffer_ != NULL);
176 }
177
178
179 void LogMessageBuilder::Append(const char* format, ...) {
180 Vector<char> buf(Log::message_buffer_ + pos_,
181 Log::kMessageBufferSize - pos_);
182 va_list args;
183 va_start(args, format);
184 Append(format, args);
185 va_end(args);
186 ASSERT(pos_ <= Log::kMessageBufferSize);
187 }
188
189
190 void LogMessageBuilder::Append(const char* format, va_list args) {
191 Vector<char> buf(Log::message_buffer_ + pos_,
192 Log::kMessageBufferSize - pos_);
193 int result = v8::internal::OS::VSNPrintF(buf, format, args);
194
195 // Result is -1 if output was truncated.
196 if (result >= 0) {
197 pos_ += result;
198 } else {
199 pos_ = Log::kMessageBufferSize;
200 }
201 ASSERT(pos_ <= Log::kMessageBufferSize);
202 }
203
204
205 void LogMessageBuilder::Append(const char c) {
206 if (pos_ < Log::kMessageBufferSize) {
207 Log::message_buffer_[pos_++] = c;
208 }
209 ASSERT(pos_ <= Log::kMessageBufferSize);
210 }
211
212
213 void LogMessageBuilder::Append(String* str) {
214 AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
215 int length = str->length();
216 for (int i = 0; i < length; i++) {
217 Append(static_cast<char>(str->Get(i)));
218 }
219 }
220
221
222 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
223 AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
224 int len = str->length();
225 if (len > 0x1000)
226 len = 0x1000;
227 if (show_impl_info) {
228 Append(str->IsAsciiRepresentation() ? 'a' : '2');
229 if (StringShape(str).IsExternal())
230 Append('e');
231 if (StringShape(str).IsSymbol())
232 Append('#');
233 Append(":%i:", str->length());
234 }
235 for (int i = 0; i < len; i++) {
236 uc32 c = str->Get(i);
237 if (c > 0xff) {
238 Append("\\u%04x", c);
239 } else if (c < 32 || c > 126) {
240 Append("\\x%02x", c);
241 } else if (c == ',') {
242 Append("\\,");
243 } else if (c == '\\') {
244 Append("\\\\");
245 } else {
246 Append("%lc", c);
247 }
248 }
249 }
250
251
252 void LogMessageBuilder::WriteToLogFile() {
253 ASSERT(pos_ <= Log::kMessageBufferSize);
254 Log::Write(Log::message_buffer_, pos_);
255 }
256
257
258 void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
259 int len = strlen(str);
260 Log::Write(str, len);
261 }
262
263 #endif // ENABLE_LOGGING_AND_PROFILING
264
265 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698