/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 2016-2016 Carbonite, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. U.M. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team. Its members are listed in a * file named AUTHORS, in the root directory of this distribution. */ /* * memory ring buffer */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "amanda.h" #include "glib.h" #include "conffile.h" #include "mem-ring.h" #define DEFAULT_MEM_RING_BLOCK_SIZE (NETWORK_BLOCK_BYTES) #define DEFAULT_MEM_RING_SIZE (DEFAULT_MEM_RING_BLOCK_SIZE*8) static void alloc_mem_ring(mem_ring_t *mem_ring); mem_ring_t * create_mem_ring(void) { mem_ring_t *mem_ring = g_new0(mem_ring_t, 1); mem_ring->mutex = g_mutex_new(); mem_ring->add_cond = g_cond_new(); mem_ring->free_cond = g_cond_new(); mem_ring->write_offset = 0; mem_ring->written = 0; mem_ring->read_offset = 0; mem_ring->readx = 0; mem_ring->eof_flag = FALSE; return mem_ring; } void mem_ring_producer_set_size( mem_ring_t *mem_ring, size_t ring_size, size_t block_size) { g_mutex_lock(mem_ring->mutex); mem_ring->producer_block_size = block_size; mem_ring->producer_ring_size = ring_size; while (mem_ring->consumer_block_size == 0 || mem_ring->consumer_ring_size == 0) { g_cond_wait(mem_ring->add_cond, mem_ring->mutex); } alloc_mem_ring(mem_ring); g_cond_broadcast(mem_ring->free_cond); g_mutex_unlock(mem_ring->mutex); } void mem_ring_consumer_set_size( mem_ring_t *mem_ring, size_t ring_size, size_t block_size) { g_mutex_lock(mem_ring->mutex); mem_ring->consumer_block_size = block_size; mem_ring->consumer_ring_size = ring_size; g_cond_broadcast(mem_ring->add_cond); g_cond_wait(mem_ring->free_cond, mem_ring->mutex); g_mutex_unlock(mem_ring->mutex); } void init_mem_ring( mem_ring_t *mem_ring, size_t ring_size, size_t block_size) { g_mutex_lock(mem_ring->mutex); mem_ring->consumer_block_size = block_size; mem_ring->producer_block_size = block_size; mem_ring->consumer_ring_size = ring_size; mem_ring->producer_ring_size = ring_size; mem_ring->ring_size = ring_size; alloc_mem_ring(mem_ring); g_mutex_unlock(mem_ring->mutex); } static void alloc_mem_ring( mem_ring_t *mem_ring) { uint64_t best_ring_size; if (mem_ring->producer_ring_size > mem_ring->consumer_ring_size) { best_ring_size = mem_ring->producer_ring_size; if (best_ring_size < mem_ring->producer_block_size * 2) best_ring_size = mem_ring->producer_block_size * 2; } else { best_ring_size = mem_ring->consumer_ring_size; if (best_ring_size < mem_ring->consumer_block_size * 2) best_ring_size = mem_ring->consumer_block_size * 2; } if (best_ring_size % mem_ring->producer_block_size != 0) { best_ring_size = ((best_ring_size % mem_ring->producer_block_size)+1) * mem_ring->producer_block_size; } while (best_ring_size % mem_ring->consumer_block_size != 0) { best_ring_size += mem_ring->producer_block_size; } mem_ring->ring_size = best_ring_size; mem_ring->buffer = malloc(mem_ring->ring_size); } void close_mem_ring( mem_ring_t *mem_ring) { g_mutex_free(mem_ring->mutex); g_cond_free(mem_ring->add_cond); g_cond_free(mem_ring->free_cond); g_free(mem_ring->buffer); g_free(mem_ring); }