Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_subr/cache-membuffer.c view on Meta::CPAN
/* Reference to the first (defined by the order content in the data
* buffer) used dictionary entry behind the insertion position
* (current_data). If NO_INDEX, the data buffer is free starting at the
* current_data offset.
*/
apr_uint32_t next;
/* Pointer to the data buffer, data_size bytes long. Never NULL.
*/
unsigned char *data;
/* Size of data buffer in bytes. Must be > 0.
*/
apr_uint64_t data_size;
/* Offset in the data buffer where the next insertion shall occur.
*/
apr_uint64_t current_data;
/* Total number of data buffer bytes in use.
*/
apr_uint64_t data_used;
/* Largest entry size that we would accept. For total cache sizes
* less than 4TB (sic!), this is determined by the total cache size.
*/
apr_uint64_t max_entry_size;
/* Number of used dictionary entries, i.e. number of cached items.
* In conjunction with hit_count, this is used calculate the average
* hit count as part of the randomized LFU algorithm.
*/
apr_uint32_t used_entries;
/* Sum of (read) hit counts of all used dictionary entries.
* In conjunction used_entries used_entries, this is used calculate
* the average hit count as part of the randomized LFU algorithm.
*/
apr_uint64_t hit_count;
/* Total number of calls to membuffer_cache_get.
* Purely statistical information that may be used for profiling.
*/
apr_uint64_t total_reads;
/* Total number of calls to membuffer_cache_set.
* Purely statistical information that may be used for profiling.
*/
apr_uint64_t total_writes;
/* Total number of hits since the cache's creation.
* Purely statistical information that may be used for profiling.
*/
apr_uint64_t total_hits;
#if APR_HAS_THREADS
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
apr_thread_rwlock_t *lock;
/* If set, write access will wait until they get exclusive access.
* Otherwise, they will become no-ops if the segment is currently
* read-locked.
*/
svn_boolean_t allow_blocking_writes;
#endif
};
/* Align integer VALUE to the next ITEM_ALIGNMENT boundary.
*/
#define ALIGN_VALUE(value) (((value) + ITEM_ALIGNMENT-1) & -ITEM_ALIGNMENT)
/* Align POINTER value to the next ITEM_ALIGNMENT boundary.
*/
#define ALIGN_POINTER(pointer) ((void*)ALIGN_VALUE((apr_size_t)(char*)(pointer)))
/* If locking is supported for CACHE, acquire a read lock for it.
*/
static svn_error_t *
read_lock_cache(svn_membuffer_t *cache)
{
#if APR_HAS_THREADS
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_rdlock(cache->lock);
if (status)
return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
}
#endif
return SVN_NO_ERROR;
}
/* If locking is supported for CACHE, acquire a write lock for it.
*/
static svn_error_t *
write_lock_cache(svn_membuffer_t *cache, svn_boolean_t *success)
{
#if APR_HAS_THREADS
if (cache->lock)
{
apr_status_t status;
if (cache->allow_blocking_writes)
{
status = apr_thread_rwlock_wrlock(cache->lock);
}
else
{
status = apr_thread_rwlock_trywrlock(cache->lock);
if (SVN_LOCK_IS_BUSY(status))
{
*success = FALSE;
status = APR_SUCCESS;
}
}
src/subversion/subversion/libsvn_subr/cache-membuffer.c view on Meta::CPAN
* than 16GB allowing for >4GB entries. But caching chunks larger
* than 4GB is simply not supported.
*/
max_entry_size = data_size / 4 > MAX_ITEM_SIZE
? MAX_ITEM_SIZE
: data_size / 4;
/* to keep the entries small, we use 32 bit indexes only
* -> we need to ensure that no more then 4G entries exist.
*
* Note, that this limit could only be exceeded in a very
* theoretical setup with about 1EB of cache.
*/
group_count = directory_size / sizeof(entry_group_t)
>= (APR_UINT32_MAX / GROUP_SIZE)
? (APR_UINT32_MAX / GROUP_SIZE) - 1
: (apr_uint32_t)(directory_size / sizeof(entry_group_t));
group_init_size = 1 + group_count / (8 * GROUP_INIT_GRANULARITY);
for (seg = 0; seg < segment_count; ++seg)
{
/* allocate buffers and initialize cache members
*/
c[seg].segment_count = (apr_uint32_t)segment_count;
c[seg].group_count = group_count;
c[seg].directory = apr_pcalloc(pool,
group_count * sizeof(entry_group_t));
/* Allocate and initialize directory entries as "not initialized",
hence "unused" */
c[seg].group_initialized = apr_pcalloc(pool, group_init_size);
c[seg].first = NO_INDEX;
c[seg].last = NO_INDEX;
c[seg].next = NO_INDEX;
c[seg].data_size = data_size;
c[seg].data = secure_aligned_alloc(pool, (apr_size_t)data_size, FALSE);
c[seg].current_data = 0;
c[seg].data_used = 0;
c[seg].max_entry_size = max_entry_size;
c[seg].used_entries = 0;
c[seg].hit_count = 0;
c[seg].total_reads = 0;
c[seg].total_writes = 0;
c[seg].total_hits = 0;
/* were allocations successful?
* If not, initialize a minimal cache structure.
*/
if (c[seg].data == NULL || c[seg].directory == NULL)
{
/* We are OOM. There is no need to proceed with "half a cache".
*/
return svn_error_wrap_apr(APR_ENOMEM, "OOM");
}
#if APR_HAS_THREADS
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
c[seg].lock = NULL;
if (thread_safe)
{
apr_status_t status =
apr_thread_rwlock_create(&(c[seg].lock), pool);
if (status)
return svn_error_wrap_apr(status, _("Can't create cache mutex"));
}
/* Select the behavior of write operations.
*/
c[seg].allow_blocking_writes = allow_blocking_writes;
#endif
}
/* done here
*/
*cache = c;
return SVN_NO_ERROR;
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND and set *FOUND accordingly.
*
* Note: This function requires the caller to serialize access.
* Don't call it directly, call entry_exists instead.
*/
static svn_error_t *
entry_exists_internal(svn_membuffer_t *cache,
apr_uint32_t group_index,
entry_key_t to_find,
svn_boolean_t *found)
{
*found = find_entry(cache, group_index, to_find, FALSE) != NULL;
return SVN_NO_ERROR;
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND and set *FOUND accordingly.
*/
static svn_error_t *
entry_exists(svn_membuffer_t *cache,
apr_uint32_t group_index,
entry_key_t to_find,
svn_boolean_t *found)
{
WITH_READ_LOCK(cache,
entry_exists_internal(cache,
group_index,
to_find,
found));
return SVN_NO_ERROR;
}
/* Try to insert the serialized item given in BUFFER with SIZE into
( run in 0.599 second using v1.01-cache-2.11-cpan-d7f47b0818f )