A C client for memcached

Brad Fitzpatrick brad at danga.com
Tue Oct 26 11:11:08 PDT 2004


Wow, nice surprise.

Are you going to host this somewhere that I can link to from the clients
page, or would you rather I host it?

As for your other comments, I'll look into them.

- Brad


On Mon, 25 Oct 2004, Sean Chittenden wrote:

> > I'd base a C implementation off the Perl version, but I'm biased.  The
> > Perl version has some minor inefficiencies, but they're things you'd
> > find
> > during a port.  Stability-wise, though, the Perl client is rock-solid.
>
> Ugh, I sure hope you don't have too much time invested in this yet.
> I've been sitting on this for a while and have been meaning to post it.
>   There are other little subtle goodies for memory management in there,
> but I haven't shown'em here.  Maybe I'll write up an mdoc(7) file for
> this if someone hounds me to get it done (ENOTIME).  Please let me know
> if someone has questions.  I'm not quite ready to have this
> incorporated into the tree (if Brad'll take it), so give me a week or
> so to collect bug reports from folks now that I've opened this up.
> It's production quality from my point of view (could be that I've got
> this code in production and haven't had any problems... not to say that
> there aren't potentially problems, but...).  Anyway, when I wrote this,
> I went to great lengths to minimize system calls and memory
> allocations.  I don't like the mc_aget() interface, but I added it
> 'cause I knew people would want it.  I'm tempted to write mc_aget2()
> and other mc_*2() calls that only take a const char *key arg instead of
> the key and its length.  I put the length everywhere because I'd like
> to keep API compatibility when memcached grows a binary API (*nudge*).
>
> Other notes that I've been meaning to post:
>
> *) flush_all + add of a flushed key gives me errors... don't think it
> should.
>
> *) The protocol.txt doc isn't quite accurate regarding stats.  I've had
> the patch in my tree for ages... it includes some trailing whitespace
> cleanups too.
>
> *) Is it intentional that a delete on a key that's in the delete hold
> queue purges the key from the delete hold queue?  Ex:  delete foo 900,
> delete foo, add foo 0 0 4  works.
>
>
> If someone nudges me enough, I'll thump out a C++ wrapper around the C
> API if there's interest.  I'm using the C API in my Qt apps, but it'd
> be nice if there was an actual C++ wrapper to lend some syntactic
> sugar.
>
> -sc
>
>
> PS  If someone can figure out why memcached runs dog slow on my
> powerbook, I'd be greatful.
>
> PPS I've only tested/used this on FreeBSD and OS-X.  I gladly welcome
> patches to make this compile on more platforms if there are problems
> (don't think there should be major portability problems though).
>
>
> // Create a new memcache instance
> struct memcache *mc = mc_new();
>
> // Add a few servers
> mc_server_add(mc, "127.0.0.1", "11211");
> mc_server_add(mc, "127.0.0.1", "11212");
> mc_server_add(mc, "127.0.0.1", "11213");
>
> // Add a key
> mc_add(mc, key, keylen, flags, expire, bytes, val);
>
> // Get a key, caller has to free(3) memory
> void *blah = mc_aget(mc, key, keylen);
> free(blah);
>
> // Perform a multi-key request
> struct memcache_req *req = mc_req_new();
> mc_req_add(req, key1, key1_len);
> mc_req_add(req, key2, key2_len);
> mc_get(mc, req);
> // Process the results (need a better interface to looping through
> results)
>
> // Perform a multi-key request the easy way (this is my preferred way
> of getting data):
> req = mc_req_new();
> res1 = mc_req_add(req, key1, key1_len);
> res2 = mc_req_add(req, key2, key2_len);
> mc_get(mc, req);
> // Play with res1/res2 w/o any looping through req
>
>
> // Complex multi-key get example:
> // Grab the response object that will be used to store a given key
> struct memcache_res *res = mc_req_add(req, key3, key3_len);
> res->size = 1024;				// Allocate our own memory a head of time (useful
> for loops)
> res->val = malloc(res->size);
> res->free_on_delete = 't';
>
> // Perform the get
> mc_get(mc, req);
> mc_res_free(req, res);
>
> // Get stats from the whole cluster
> struct memcache_server_stats *s = mc_stats(mc);
> mc_server_stats_free(s);
>
> // Storage commands:
> mc_add(mc, key, key_len, flags, expire, bytes, val);
> mc_replace(mc, key, key_len, flags, expire, bytes, val);
> mc_set(mc, key, key_len, flags, expire, bytes, val);
>
> // Delete commands:
> mc_delete(mc, key, key_len, hold_timer);
>
> // Atomic opts:
> mc_incr(mc, key, key_len, 1);
> mc_decr(mc, key, key_len, 1);
>
> mc_free(mc);
>
>
>


More information about the memcached mailing list