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 )