"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/stats_prefix.c" (21 Feb 2022, 4441 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stats_prefix.c" see the Fossies "Dox" file reference documentation.

    1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    2 /* Author: Steven Grimm <sgrimm@facebook.com> */
    3 #include "memcached.h"
    4 #include <stdio.h>
    5 #include <stdlib.h>
    6 #include <string.h>
    7 #include <assert.h>
    8 
    9 /* Hash table that uses the global hash function */
   10 static PREFIX_STATS *prefix_stats[PREFIX_HASH_SIZE];
   11 
   12 static char prefix_delimiter;
   13 static int num_prefixes = 0;
   14 static int total_prefix_size = 0;
   15 
   16 void stats_prefix_init(char delimiter) {
   17     prefix_delimiter = delimiter;
   18     memset(prefix_stats, 0, sizeof(prefix_stats));
   19 }
   20 
   21 void stats_prefix_clear(void) {
   22     int i;
   23 
   24     for (i = 0; i < PREFIX_HASH_SIZE; i++) {
   25         PREFIX_STATS *cur, *next;
   26         for (cur = prefix_stats[i]; cur != NULL; cur = next) {
   27             next = cur->next;
   28             free(cur->prefix);
   29             free(cur);
   30         }
   31         prefix_stats[i] = NULL;
   32     }
   33     num_prefixes = 0;
   34     total_prefix_size = 0;
   35 }
   36 
   37 PREFIX_STATS *stats_prefix_find(const char *key, const size_t nkey) {
   38     PREFIX_STATS *pfs;
   39     uint32_t hashval;
   40     size_t length;
   41     bool bailout = true;
   42 
   43     assert(key != NULL);
   44 
   45     for (length = 0; length < nkey && key[length] != '\0'; length++) {
   46         if (key[length] == prefix_delimiter) {
   47             bailout = false;
   48             break;
   49         }
   50     }
   51 
   52     if (bailout) {
   53         return NULL;
   54     }
   55 
   56     hashval = hash(key, length) % PREFIX_HASH_SIZE;
   57 
   58     for (pfs = prefix_stats[hashval]; NULL != pfs; pfs = pfs->next) {
   59         if (strncmp(pfs->prefix, key, length) == 0)
   60             return pfs;
   61     }
   62 
   63     pfs = calloc(sizeof(PREFIX_STATS), 1);
   64     if (NULL == pfs) {
   65         perror("Can't allocate space for stats structure: calloc");
   66         return NULL;
   67     }
   68 
   69     pfs->prefix = malloc(length + 1);
   70     if (NULL == pfs->prefix) {
   71         perror("Can't allocate space for copy of prefix: malloc");
   72         free(pfs);
   73         return NULL;
   74     }
   75 
   76     strncpy(pfs->prefix, key, length);
   77     pfs->prefix[length] = '\0';      /* because strncpy() sucks */
   78     pfs->prefix_len = length;
   79 
   80     pfs->next = prefix_stats[hashval];
   81     prefix_stats[hashval] = pfs;
   82 
   83     num_prefixes++;
   84     total_prefix_size += length;
   85 
   86     return pfs;
   87 }
   88 
   89 void stats_prefix_record_get(const char *key, const size_t nkey, const bool is_hit) {
   90     PREFIX_STATS *pfs;
   91 
   92     STATS_LOCK();
   93     pfs = stats_prefix_find(key, nkey);
   94     if (NULL != pfs) {
   95         pfs->num_gets++;
   96         if (is_hit) {
   97             pfs->num_hits++;
   98         }
   99     }
  100     STATS_UNLOCK();
  101 }
  102 
  103 void stats_prefix_record_delete(const char *key, const size_t nkey) {
  104     PREFIX_STATS *pfs;
  105 
  106     STATS_LOCK();
  107     pfs = stats_prefix_find(key, nkey);
  108     if (NULL != pfs) {
  109         pfs->num_deletes++;
  110     }
  111     STATS_UNLOCK();
  112 }
  113 
  114 void stats_prefix_record_set(const char *key, const size_t nkey) {
  115     PREFIX_STATS *pfs;
  116 
  117     STATS_LOCK();
  118     pfs = stats_prefix_find(key, nkey);
  119     if (NULL != pfs) {
  120         pfs->num_sets++;
  121     }
  122     STATS_UNLOCK();
  123 }
  124 
  125 char *stats_prefix_dump(int *length) {
  126     const char *format = "PREFIX %s get %llu hit %llu set %llu del %llu\r\n";
  127     PREFIX_STATS *pfs;
  128     char *buf;
  129     int i, pos;
  130     size_t size = 0, written = 0;
  131 #ifndef NDEBUG
  132     size_t total_written = 0;
  133 #endif
  134     /*
  135      * Figure out how big the buffer needs to be. This is the sum of the
  136      * lengths of the prefixes themselves, plus the size of one copy of
  137      * the per-prefix output with 20-digit values for all the counts,
  138      * plus space for the "END" at the end.
  139      */
  140     STATS_LOCK();
  141     size = strlen(format) + total_prefix_size +
  142            num_prefixes * (strlen(format) - 2 /* %s */
  143                            + 4 * (20 - 4)) /* %llu replaced by 20-digit num */
  144                            + sizeof("END\r\n");
  145     buf = malloc(size);
  146     if (NULL == buf) {
  147         perror("Can't allocate stats response: malloc");
  148         STATS_UNLOCK();
  149         return NULL;
  150     }
  151 
  152     pos = 0;
  153     for (i = 0; i < PREFIX_HASH_SIZE; i++) {
  154         for (pfs = prefix_stats[i]; NULL != pfs; pfs = pfs->next) {
  155             written = snprintf(buf + pos, size-pos, format,
  156                            pfs->prefix, pfs->num_gets, pfs->num_hits,
  157                            pfs->num_sets, pfs->num_deletes);
  158             pos += written;
  159 #ifndef NDEBUG
  160             total_written += written;
  161             assert(total_written < size);
  162 #endif
  163         }
  164     }
  165 
  166     STATS_UNLOCK();
  167     memcpy(buf + pos, "END\r\n", 6);
  168 
  169     *length = pos + 5;
  170     return buf;
  171 }