2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
6 #include <DebugEventStream.h>
13 #include <system_profiler_defs.h>
16 #define INPUT_BUFFER_SIZE (128 * 1024)
19 BDebugEventInputStream::BDebugEventInputStream()
34 BDebugEventInputStream::~BDebugEventInputStream()
44 BDebugEventInputStream::SetTo(BDataIO
* stream
)
55 if (fBuffer
== NULL
) {
56 fBuffer
= (uint8
*)malloc(INPUT_BUFFER_SIZE
);
57 if (fBuffer
== NULL
) {
63 fBufferCapacity
= INPUT_BUFFER_SIZE
;
72 BDebugEventInputStream::SetTo(const void* data
, size_t size
,
73 bool takeOverOwnership
)
77 if (data
== NULL
|| size
== 0)
80 if (fBuffer
!= NULL
) {
88 fBuffer
= (uint8
*)data
;
89 fBufferCapacity
= fBufferSize
= size
;
90 fOwnsBuffer
= takeOverOwnership
;
97 BDebugEventInputStream::Unset()
103 // If we have a buffer that we own and has the right size, we keep it.
105 if (fBuffer
!= NULL
&& fBufferSize
!= INPUT_BUFFER_SIZE
) {
120 BDebugEventInputStream::Seek(off_t streamOffset
)
122 // TODO: Support for streams, at least for BPositionIOs.
124 return B_UNSUPPORTED
;
126 if (streamOffset
< 0 || streamOffset
> (off_t
)fBufferCapacity
)
127 return B_BUFFER_OVERFLOW
;
130 fBufferPosition
= streamOffset
;
131 fBufferSize
= fBufferCapacity
- streamOffset
;
137 /*! \brief Returns the next event in the stream.
139 At the end of the stream \c 0 is returned and \c *_buffer is set to \c NULL.
140 For events that don't have data associated with them, \c *_buffer will still
141 be non-NULL, even if dereferencing that address is not allowed.
143 \param _event Pointer to a pre-allocated location where the event ID shall
145 \param _cpu Pointer to a pre-allocated location where the CPU index shall
147 \param _buffer Pointer to a pre-allocated location where the pointer to the
148 event data shall be stored.
149 \param _streamOffset Pointer to a pre-allocated location where the event
150 header's offset relative to the beginning of the stream shall be stored.
152 \return A negative error code in case an error occurred while trying to read
153 the info, the size of the data associated with the event otherwise.
156 BDebugEventInputStream::ReadNextEvent(uint32
* _event
, uint32
* _cpu
,
157 const void** _buffer
, off_t
* _streamOffset
)
159 // get the next header
160 status_t error
= _GetData(sizeof(system_profiler_event_header
));
162 if (error
== B_BAD_DATA
&& fBufferSize
== 0) {
169 system_profiler_event_header header
170 = *(system_profiler_event_header
*)(fBuffer
+ fBufferPosition
);
172 off_t streamOffset
= fStreamPosition
+ fBufferPosition
;
174 // skip the header in the buffer
175 fBufferSize
-= sizeof(system_profiler_event_header
);
176 fBufferPosition
+= sizeof(system_profiler_event_header
);
179 if (header
.size
> 0) {
180 error
= _GetData(header
.size
);
185 *_event
= header
.event
;
187 *_buffer
= fBuffer
+ fBufferPosition
;
189 *_streamOffset
= streamOffset
;
191 // skip the event in the buffer
192 fBufferSize
-= header
.size
;
193 fBufferPosition
+= header
.size
;
200 BDebugEventInputStream::_Init()
206 status_t error
= _GetData(sizeof(debug_event_stream_header
));
211 const debug_event_stream_header
& header
212 = *(const debug_event_stream_header
*)(fBuffer
+ fBufferPosition
);
214 fBufferPosition
+= sizeof(debug_event_stream_header
);
215 fBufferSize
-= sizeof(debug_event_stream_header
);
218 if (strncmp(header
.signature
, B_DEBUG_EVENT_STREAM_SIGNATURE
,
219 sizeof(header
.signature
)) != 0
220 || header
.version
!= B_DEBUG_EVENT_STREAM_VERSION
221 || (header
.flags
& B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN
) == 0) {
222 // TODO: Support non-host endianess!
227 fFlags
= header
.flags
;
228 fEventMask
= header
.event_mask
;
235 BDebugEventInputStream::_Read(void* _buffer
, size_t size
)
237 uint8
* buffer
= (uint8
*)_buffer
;
238 size_t totalBytesRead
= 0;
239 ssize_t bytesRead
= 0;
241 while (size
> 0 && (bytesRead
= fStream
->Read(buffer
, size
)) > 0) {
242 totalBytesRead
+= bytesRead
;
250 return totalBytesRead
;
255 BDebugEventInputStream::_GetData(size_t size
)
257 if (fBufferSize
>= size
)
260 if (size
> fBufferCapacity
)
261 return B_BUFFER_OVERFLOW
;
263 // move remaining data to the start of the buffer
264 if (fBufferSize
> 0 && fBufferPosition
> 0)
265 memmove(fBuffer
, fBuffer
+ fBufferPosition
, fBufferSize
);
266 fStreamPosition
+= fBufferPosition
;
270 if (fStream
!= NULL
) {
271 ssize_t bytesRead
= _Read(fBuffer
+ fBufferSize
,
272 fBufferCapacity
- fBufferSize
);
276 fBufferSize
+= bytesRead
;
279 return fBufferSize
>= size
? B_OK
: B_BAD_DATA
;
283 // #pragma mark - BDebugEventOutputStream
286 BDebugEventOutputStream::BDebugEventOutputStream()
294 BDebugEventOutputStream::~BDebugEventOutputStream()
301 BDebugEventOutputStream::SetTo(BDataIO
* stream
, uint32 flags
, uint32 eventMask
)
305 // set the new values
310 fFlags
= /*(flags & B_DEBUG_EVENT_STREAM_FLAG_ZIPPED)
311 |*/ B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN
;
312 // TODO: Support zipped data!
314 // init and write the header
315 debug_event_stream_header header
;
316 memset(header
.signature
, 0, sizeof(header
.signature
));
317 strlcpy(header
.signature
, B_DEBUG_EVENT_STREAM_SIGNATURE
,
318 sizeof(header
.signature
));
319 header
.version
= B_DEBUG_EVENT_STREAM_VERSION
;
320 header
.flags
= fFlags
;
321 header
.event_mask
= eventMask
;
323 ssize_t written
= fStream
->Write(&header
, sizeof(header
));
328 if ((size_t)written
!= sizeof(header
)) {
338 BDebugEventOutputStream::Unset()
347 BDebugEventOutputStream::Write(const void* buffer
, size_t size
)
354 ssize_t written
= fStream
->Write(buffer
, size
);
357 if ((size_t)written
!= size
)
365 BDebugEventOutputStream::Flush()