Alien-SVN

 view release on metacpan or  search on metacpan

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

 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 */

#include <apr_md5.h>

#include "svn_pools.h"
#include "svn_base64.h"
#include "svn_path.h"

#include "svn_private_config.h"
#include "private/svn_cache.h"
#include "private/svn_dep_compat.h"

#include "cache.h"

#ifdef SVN_HAVE_MEMCACHE

#include <apr_memcache.h>

/* A note on thread safety:

   The apr_memcache_t object does its own mutex handling, and nothing
   else in memcache_t is ever modified, so this implementation should
   be fully thread-safe.
*/

/* The (internal) cache object. */
typedef struct memcache_t {
  /* The memcached server set we're using. */
  apr_memcache_t *memcache;

  /* A prefix used to differentiate our data from any other data in
   * the memcached (URI-encoded). */
  const char *prefix;

  /* The size of the key: either a fixed number of bytes or
   * APR_HASH_KEY_STRING. */
  apr_ssize_t klen;


  /* Used to marshal values in and out of the cache. */
  svn_cache__serialize_func_t serialize_func;
  svn_cache__deserialize_func_t deserialize_func;
} memcache_t;

/* The wrapper around apr_memcache_t. */
struct svn_memcache_t {
  apr_memcache_t *c;
};


/* The memcached protocol says the maximum key length is 250.  Let's
   just say 249, to be safe. */
#define MAX_MEMCACHED_KEY_LEN 249
#define MEMCACHED_KEY_UNHASHED_LEN (MAX_MEMCACHED_KEY_LEN - \
                                    2 * APR_MD5_DIGESTSIZE)


/* Set *MC_KEY to a memcache key for the given key KEY for CACHE, allocated
   in POOL. */
static svn_error_t *
build_key(const char **mc_key,
          memcache_t *cache,
          const void *raw_key,
          apr_pool_t *pool)
{
  const char *encoded_suffix;
  const char *long_key;
  apr_size_t long_key_len;

  if (cache->klen == APR_HASH_KEY_STRING)
    encoded_suffix = svn_path_uri_encode(raw_key, pool);
  else
    {
      const svn_string_t *raw = svn_string_ncreate(raw_key, cache->klen, pool);
      const svn_string_t *encoded = svn_base64_encode_string2(raw, FALSE,
                                                              pool);
      encoded_suffix = encoded->data;
    }

  long_key = apr_pstrcat(pool, "SVN:", cache->prefix, ":", encoded_suffix,
                         (char *)NULL);
  long_key_len = strlen(long_key);

  /* We don't want to have a key that's too big.  If it was going to
     be too big, we MD5 the entire string, then replace the last bit
     with the checksum.  Note that APR_MD5_DIGESTSIZE is for the pure
     binary digest; we have to double that when we convert to hex.

     Every key we use will either be at most
     MEMCACHED_KEY_UNHASHED_LEN bytes long, or be exactly
     MAX_MEMCACHED_KEY_LEN bytes long. */
  if (long_key_len > MEMCACHED_KEY_UNHASHED_LEN)
    {
      svn_checksum_t *checksum;
      SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, long_key, long_key_len,
                           pool));

      long_key = apr_pstrcat(pool,
                             apr_pstrmemdup(pool, long_key,
                                            MEMCACHED_KEY_UNHASHED_LEN),
                             svn_checksum_to_cstring_display(checksum, pool),
                             (char *)NULL);
    }

  *mc_key = long_key;
  return SVN_NO_ERROR;
}

/* Core functionality of our getter functions: fetch DATA from the memcached
 * given by CACHE_VOID and identified by KEY. Indicate success in FOUND and
 * use a tempoary sub-pool of POOL for allocations.
 */



( run in 0.484 second using v1.01-cache-2.11-cpan-483215c6ad5 )