Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_subr/cache-inprocess.c  view on Meta::CPAN

#include <assert.h>

#include <apr_thread_mutex.h>

#include "svn_pools.h"

#include "svn_private_config.h"

#include "cache.h"
#include "private/svn_mutex.h"

/* The (internal) cache object. */
typedef struct inprocess_cache_t {
  /* A user-defined identifier for this cache instance. */
  const char *id;

  /* HASH maps a key (of size KLEN) to a struct cache_entry. */
  apr_hash_t *hash;
  apr_ssize_t klen;

  /* Used to copy values into the cache. */
  svn_cache__serialize_func_t serialize_func;

  /* Used to copy values out of the cache. */
  svn_cache__deserialize_func_t deserialize_func;

  /* Maximum number of pages that this cache instance may allocate */
  apr_uint64_t total_pages;
  /* The number of pages we're allowed to allocate before having to
   * try to reuse one. */
  apr_uint64_t unallocated_pages;
  /* Number of cache entries stored on each page.  Must be at least 1. */
  apr_uint64_t items_per_page;

  /* A dummy cache_page serving as the head of a circular doubly
   * linked list of cache_pages.  SENTINEL->NEXT is the most recently
   * used page, and SENTINEL->PREV is the least recently used page.
   * All pages in this list are "full"; the page currently being
   * filled (PARTIAL_PAGE) is not in the list. */
  struct cache_page *sentinel;

  /* A page currently being filled with entries, or NULL if there's no
   * partially-filled page.  This page is not in SENTINEL's list. */
  struct cache_page *partial_page;
  /* If PARTIAL_PAGE is not null, this is the number of entries
   * currently on PARTIAL_PAGE. */
  apr_uint64_t partial_page_number_filled;

  /* The pool that the svn_cache__t itself, HASH, and all pages are
   * allocated in; subpools of this pool are used for the cache_entry
   * structs, as well as the dup'd values and hash keys.
   */
  apr_pool_t *cache_pool;

  /* Sum of the SIZE members of all cache_entry elements that are
   * accessible from HASH. This is used to make statistics available
   * even if the sub-pools have already been destroyed.
   */
  apr_size_t data_size;

  /* 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. */
  svn_mutex__t *mutex;
} inprocess_cache_t;

/* A cache page; all items on the page are allocated from the same
 * pool. */
struct cache_page {
  /* Pointers for the LRU list anchored at the cache's SENTINEL.
   * (NULL for the PARTIAL_PAGE.) */
  struct cache_page *prev;
  struct cache_page *next;

  /* The pool in which cache_entry structs, hash keys, and dup'd
   * values are allocated.  The CACHE_PAGE structs are allocated
   * in CACHE_POOL and have the same lifetime as the cache itself.
   * (The cache will never allocate more than TOTAL_PAGES page
   * structs (inclusive of the sentinel) from CACHE_POOL.)
   */
  apr_pool_t *page_pool;

  /* A singly linked list of the entries on this page; used to remove
   * them from the cache's HASH before reusing the page. */
  struct cache_entry *first_entry;
};

/* An cache entry. */
struct cache_entry {
  const void *key;

  /* serialized value */
  void *value;

  /* length of the serialized value in bytes */
  apr_size_t size;

  /* The page it's on (needed so that the LRU list can be
   * maintained). */
  struct cache_page *page;

  /* Next entry on the page. */
  struct cache_entry *next_entry;
};


/* Removes PAGE from the doubly-linked list it is in (leaving its PREV
 * and NEXT fields undefined). */
static void
remove_page_from_list(struct cache_page *page)
{
  page->prev->next = page->next;
  page->next->prev = page->prev;
}

/* Inserts PAGE after CACHE's sentinel. */
static void
insert_page(inprocess_cache_t *cache,
            struct cache_page *page)
{
  struct cache_page *pred = cache->sentinel;



( run in 0.884 second using v1.01-cache-2.11-cpan-d7f47b0818f )