C API help

Evan Martin martine@danga.com
Wed, 18 Feb 2004 20:46:47 -0800


I have my old client that seems to do get and set tolerably well, but
I'm not sure it's the API we want:

/* this will take in a server list */
MemCacheClient* memcachec_new(void);

void* memcachec_get(MemCacheClient *mc, char *key, int *rlen);
int   memcachec_set(MemCacheClient *mc, char *key,
                    void *val, int len, time_t exp);

The problem here is that memcachec_get returns allocated memory, which
is fine for your typical day to day applications (and is what Perl does,
after all) but for C-level languages it's probably more appropriate to
use a client-provided buffer.  (Isn't this what Brian Aker wanted for
MySQL?)

I can think of a few ways to do it:

 - int memcachec_get(MemCacheClient *mc, char *key, void *buf, int max);

   which would read at most max bytes and store them into buf, returning
   how many bytes were read in the int.  This is fine if you know how
   much data you're getting, but what if you don't?

 - int memcachec_start_get(MemCacheClient *mc, char *key);
     starts the get, returns number of bytes in the key.
   int memcachec_read(MemCacheClient *mc, char *key, void *buf, int len);
     which must be called after start_get, and repeatedly called until
     you've retrieved len bytes.
   but that's weird because of all the "you musts".
 
 - int memcachec_get(MemCacheClient *mc, char *key,
                     int (*cb)(void *env, void *data, int len),
		     void *env);
   which repeatedly calls cb with more and more data.
   or something like that.
   This looks pretty ugly, but we'll definitely need a function like
   this for get_multi, unless we want to have it return something like a
   linked lists of structs (key, value pairs).


Maybe I should elaborate on that get_multi comment.
If we follow the form of the topmost API, where the we return
allocated memory:
  int get_multi(MemCacheClient *mc, char **keys, int keycount,
                int (*cb)(void *env, char *key, void *val, int len),
                void *env);
The enduser could easily hook this up to, for example, a hash table,
by providing the appropriate cb and env.  But callbacks are annoying.
But C is annoying, when you're spoiled by nicer languages.  :)

Any thoughts?

-- 
Evan Martin
martine@danga.com
http://neugierig.org