A C client for memcached

Mahmoud Al Gammal mahmoudfg at gawab.com
Mon Oct 25 23:42:36 PDT 2004


Sean Chittenden writes:

> 
>> 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 

Not really...thanks a lot :)

> 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).

I'm going to be using it on Linux. I'll certainly inform you of
any modifications required to get it running.

> 
> 
> // 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);
> 
> 

Thanks again for your effort...it sure saved me a lot of time.

Mahmoud
---------------------------------------------
Free POP3 Email from www.Gawab.com 
Sign up NOW and get your account @gawab.com!!


More information about the memcached mailing list