On 06.03.2010 17:10, Ingo Weinhold wrote:
Come to think of it, the space problem occurs only during the boot process, before the syslog daemon is running. I guess we should simply allocate a more generous buffer for the boot process and shrink it back once the buffer has been emptied. CU, Ingo
Ok, I looked into how to figure out when the buffer is empty to shrink the syslog buffer again this is what I came up with something like this:
modifying syslog_sender in debug.cpp (note this is only a sketch to show what I'm up to):
while (true){ <snip> if (port >= B_OK) { if (!bufferPending) { // we need to have exclusive access to our syslog buffer cpu_status state = disable_interrupts(); acquire_spinlock(&sSpinlock); length = ring_buffer_readable(sSyslogBuffer); if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH) length = SYSLOG_MAX_MESSAGE_LENGTH; length = ring_buffer_read(sSyslogBuffer, (uint8*)sSyslogMessage->message, length); if (sSyslogDropped) {// Add drop marker - since parts had to be dropped, it's // guaranteed that we have enough space in the buffer now.
ring_buffer_write(sSyslogBuffer, (uint8*)"<DROP>", 6); sSyslogDropped = false; } + if (sSyslogBuffer->resizeCount == 0) + downsize_ring_buffer_if_empty(sSyslogBuffer); release_spinlock(&sSpinlock); restore_interrupts(state); } <snip> } modifiying ring_buffer: struct ring_buffer { int32 first; int32 in; int32 size; + int32 resizeCount; // Counts how often the buffer was resized uint8 buffer[0]; }; +/* Downsizes the passed parameter only when + 1. The new size is smaller then the current size + 2. Memory for the downsized buffer can be allocated. + 3. The buffer is currently empty. + If downsizing fails the original buffer will be untouched. + */ +void +downsize_ring_buffer_if_empty(struct ring_buffer* currentBuffer, + size_t newSize = DEFAULT_SYSLOG_BUFFER_SIZE) +{ + if (currentBuffer->size > newSize && currentBuffer->size == 0) { + struct ring_buffer* newBuffer = create_ring_buffer(newSize); + if (newBuffer == NULL) + return; + + newBuffer->resizeCount = currentBuffer->resizeCount + delete_ring_buffer(currentBuffer); + newBuffer->resizeCount++; + currentBuffer = newBuffer; + } +}My main concerns about this implementation is regarding the syslog_sender where the check for downsizing happens all the time. Would this be neglectable or is there another solution I'm just missing?
And as it turned out, the maximum syslog_buffer_size is hardcoded to 262144 Bytes (which i wasn't aware of), though my original proposal of roughly 1 MB would scale down to this maximum value, in the end. So maybe the dynamic downsizing is needed anyway.,
Kind Regards -Colin