MCPcopy Create free account
hub / github.com/apache/trafficserver / _checkout_write

Method _checkout_write

src/proxy/logging/LogObject.cc:342–453  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

340}
341
342LogBuffer *
343LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
344{
345 LogBuffer::LB_ResultCode result_code;
346 LogBuffer *buffer;
347 LogBuffer *new_buffer = nullptr;
348 bool retry = true;
349 head_p old_h;
350
351 do {
352 // To avoid a race condition, we keep a count of held references in
353 // the pointer itself and add this to m_outstanding_references.
354
355 // Increment the version of m_log_buffer, returning the previous version.
356 head_p h = increment_pointer_version(&m_log_buffer);
357
358 buffer = static_cast<LogBuffer *>(FREELIST_POINTER(h));
359 result_code = buffer->checkout_write(write_offset, bytes_needed);
360 bool decremented = false;
361
362 switch (result_code) {
363 case LogBuffer::LB_OK:
364 // checkout succeeded
365 retry = false;
366 break;
367
368 case LogBuffer::LB_FULL_ACTIVE_WRITERS:
369 case LogBuffer::LB_FULL_NO_WRITERS:
370 // no more room in current buffer, create a new one
371 new_buffer = new LogBuffer(Log::config, this, Log::config->log_buffer_size);
372
373 // swap the new buffer for the old one
374 INK_WRITE_MEMORY_BARRIER;
375
376 do {
377 INK_QUEUE_LD(old_h, m_log_buffer);
378 // we may depend on comparing the old pointer to the new pointer to detect buffer swaps
379 // without worrying about pointer collisions because we always allocate a new LogBuffer
380 // before freeing the old one
381 if (FREELIST_POINTER(old_h) != FREELIST_POINTER(h)) {
382 ink_atomic_increment(&buffer->m_references, -1);
383
384 // another thread is already creating a new buffer,
385 // so delete new_buffer and try again next loop iteration
386 delete new_buffer;
387 new_buffer = nullptr;
388 break;
389 }
390 } while (write_pointer_version(&m_log_buffer, old_h, new_buffer, 0) == false);
391
392 if (FREELIST_POINTER(old_h) == FREELIST_POINTER(h)) {
393 ink_atomic_increment(&buffer->m_references, FREELIST_VERSION(old_h) - 1);
394
395 int idx = m_buffer_manager_idx++ % m_flush_threads;
396 Dbg(dbg_ctl_log_logbuffer, "adding buffer %d to flush list after checkout", buffer->get_id());
397 m_buffer_manager[idx].add_to_flush_queue(buffer);
398 Log::preproc_notify[idx].signal();
399 buffer = nullptr;

Callers

nothing calls this directly

Calls 7

ink_atomic_incrementFunction · 0.85
write_pointer_versionFunction · 0.85
checkout_writeMethod · 0.80
add_to_flush_queueMethod · 0.80
get_idMethod · 0.45
signalMethod · 0.45

Tested by

no test coverage detected