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