--- a/memcache.h Thu Aug 28 00:29:39 2008 +0300
+++ b/memcache.h Thu Aug 28 01:34:14 2008 +0300
@@ -21,7 +21,24 @@
* Keys used
*/
struct memcache_key {
+ /*
+ * Pointer to a char buffer containing the key itself.
+ *
+ * A key is a text tring which should uniquely identify a cache entry.
+ *
+ * The length limit for a key is usually 250 characters, but this is imposed by the server side (a longer key will
+ * presumeably cause a CLIENT_ERROR reply).
+ *
+ * The key should presumeably also not contain any spaces, carriage returns or newlines, as these are used to
+ * delimit tokens in the protocol itself.
+ *
+ * The buffer does not need to be zero-terminated.
+ */
char *buf;
+
+ /*
+ * The length of the key buffer in bytes. This does not include a NUL byte.
+ */
size_t len;
};
@@ -29,9 +46,27 @@
* Object attributes
*/
struct memcache_obj {
+ /*
+ * An arbitrary 16-bit (32-bit for >1.2.1) that the server stores transparently.
+ */
unsigned int flags;
+
+ /*
+ * Expiration time. If non-zero, either an offset in seconds from current time (up to 60*60*24*30 seconds, or 30d),
+ * or an absolute 32-bit unix timestamp.
+ */
time_t exptime;
+
+ /*
+ * Number of bytes in the entry. This may be zero, in which case there will be no data.
+ */
size_t bytes;
+
+ /*
+ * Used for the CMD_STORE_CAS command. An unique 64-bit value that changes if the entry is modified.
+ *
+ * Not needed for other commands, and may or may not be provided by CMD_FETCH_GET (will be set to zero).
+ */
unsigned long long cas;
};
@@ -39,8 +74,21 @@
* Object data
*/
struct memcache_buf {
+ /*
+ * The char buffer containing the data.
+ */
char *data;
+
+ /*
+ * The total length of the char buffer, and thence the cache entry.
+ */
size_t len;
+
+ /*
+ * The amount of data currently available in the buffer. This is used to provide streaming fetches.
+ *
+ * This field is *IMPORTANT*! Don't disregard it, or you *will* get incomplete data.
+ */
size_t offset;
};
@@ -49,33 +97,124 @@
*/
enum memcache_command {
MEMCACHE_CMD_INVALID,
+
+ /*
+ * Retrieve the value of a key from the memcached server.
+ *
+ * If the key exists, you will get a RPL_VALUE reply followed by a RPL_END reply.
+ * If it does not exist, you will just get a RPL_END reply.
+ */
+ MEMCACHE_CMD_FETCH_GET,
- MEMCACHE_CMD_FETCH_GET,
+ /*
+ * Store this data.
+ *
+ * Returns either RPL_STORED or RPL_NOT_STORED.
+ */
MEMCACHE_CMD_STORE_SET,
+
+ /*
+ * Store this data, but only if the server doesn't already hold data for this key.
+ *
+ * Returns either RPL_STORED or RPL_NOT_STORED.
+ */
MEMCACHE_CMD_STORE_ADD,
+
+ /*
+ * Store this data, but only if the server does already hold data for this key.
+ *
+ * Returns either RPL_STORED or RPL_NOT_STORED.
+ */
MEMCACHE_CMD_STORE_REPLACE,
+
+ /*
+ * Add this data to an existing key after existing data.
+ *
+ * obj.flags and obj.exptime are ignored.
+ *
+ * Returns ???
+ */
MEMCACHE_CMD_STORE_APPEND,
+
+ /*
+ * Add this data to an existing key before existing data.
+ *
+ * obj.flags and obj.exptime are ignored.
+ *
+ * Returns ???
+ */
MEMCACHE_CMD_STORE_PREPEND,
+
+ /*
+ * Check and Set - store this data but only if no one else had updated it since I last fetched it.
+ *
+ * obj.cas is required.
+ *
+ * Returns RPL_STORED, RPL_NOT_STORED, RPL_EXISTS (data has been modified), or RPL_NOT_FOUND (the item does not
+ * exist or has been deleted).
+ */
MEMCACHE_CMD_STORE_CAS,
MEMCACHE_CMD_MAX,
};
+/*
+ * Replies from the server
+ */
enum memcache_reply {
MEMCACHE_RPL_INVALID,
+
+ /*
+ * The library sent an unknown command. This probably means the server is not compatible with said command.
+ */
+ MEMCACHE_RPL_ERROR,
- MEMCACHE_RPL_ERROR,
+ /*
+ * There was an error in the request that the library sent. The error message is printed out via ERROR.
+ */
MEMCACHE_RPL_CLIENT_ERROR,
+
+ /*
+ * There was an error with the server when processing the request. The error message is printed out via ERROR.
+ */
MEMCACHE_RPL_SERVER_ERROR,
- // MEMCACHE_CMD_FETCH_*
+ // CMD_FETCH_*
+
+ /*
+ * The given key was found in the cache. The obj attributes are now known, and the buf data is on the way.
+ */
MEMCACHE_RPL_VALUE,
+
+ /*
+ * No more RPL_VALUE replies will be sent. This may be the only reply sent if the key was not found.
+ */
MEMCACHE_RPL_END,
- // MEMCACHE_CMD_STORE_*
+ // CMD_STORE_*
+
+ /*
+ * The object was succesfully stored in the cache.
+ */
MEMCACHE_RPL_STORED,
+
+ /*
+ * The object was not stored in the cache.
+ *
+ * This could be for a number of reasons, perhaps the object is too large, the cache is full, the key is in the
+ * delete queue, or some condition imposed by the STORE_* command was not met.
+ */
MEMCACHE_RPL_NOT_STORED,
+
+ /*
+ * The item you were trying to store with a STORE_CAS request has been modified since you last fetched it (i.e.
+ * obj.cas does not match).
+ */
MEMCACHE_RPL_EXISTS,
+
+ /*
+ * The item you were trying to store with a STORE_CAS request did not exist (or has been deleted).
+ */
MEMCACHE_RPL_NOT_FOUND,
MEMCACHE_RPL_MAX,
@@ -83,15 +222,50 @@
enum memcache_req_state {
MEMCACHE_STATE_INVALID,
+
+ /*
+ * The request is queued, and has not been sent yet
+ */
+ MEMCACHE_STATE_QUEUED,
- MEMCACHE_STATE_QUEUED,
+ /*
+ * The request is being sent, and the reply has not yet been received
+ */
MEMCACHE_STATE_SEND,
+
+ /*
+ * The reply has been received.
+ *
+ * req_reply and req_obj will return a non-NULL value, but there is no reply data yet.
+ */
MEMCACHE_STATE_REPLY,
- MEMCACHE_STATE_REPLY_DATA,
+ /*
+ * The reply and part of the reply data has been received.
+ *
+ * req_reply, req_obj and req_buf will all return non-NULL values, but buf.offset will be smaller than buf.len.
+ */
+ MEMCACHE_STATE_REPLY_DATA,
+
+ /*
+ * The full reply has been received.
+ *
+ * req_reply, req_obj will return a non-NULL value, but there is no reply data.
+ */
MEMCACHE_STATE_DONE,
+
+ /*
+ * The full reply and reply data has been received.
+ *
+ * req_reply, req_obj and req_buf will all return non-NULL values, and buf.offset will be equal to buf.len.
+ */
MEMCACHE_STATE_DATA_DONE,
-
+
+ /*
+ * An error has occurred.
+ *
+ * req_reply, req_obj and req_buf may or may not work.
+ */
MEMCACHE_STATE_ERROR,
};
@@ -112,27 +286,94 @@
/*
* Attempt to fetch a key from the cache.
+ *
+ * The state machine will work as follows:
+ *
+ * req_state multi req_reply
+ * ---------------------------------------------
+ * STATE_QUEUE ?
+ * STATE_SEND
+ * STATE_REPLY RPL_VALUE
+ * STATE_REPLY_DATA * RPL_VALUE
+ * STATE_DATA_DONE RPL_END
+ *
+ * STATE_DONE RPL_END
+ *
+ * STATE_ERROR RPL_{ERROR,CLIENT_ERROR,SERVER_ERROR}
+ *
+ * The item attributes/data can be accessed via req_obj/req_buf as described in `enum memcache_state`.
*/
struct memcache_req *memcache_fetch (struct memcache *mc, const struct memcache_key *key, void *cb_arg);
/*
- * Attempt to store a key into the cache
+ * Attempt to store an item into the cache.
+ *
+ * The cmd argument can be used to specify what CMD_STORE_* command to use.
+ *
+ * The given memcache_key is copied, including the char array pointed to by buf.
+ * Both obj and buf are also copied, but buf.data will not be copied - the pointer must remain valid until the request is done.
+ *
+ * The state machine will work as follows:
+ *
+ * req_state multi req_reply
+ * ---------------------------------------------
+ * STATE_QUEUE ?
+ * STATE_SEND
+ * STATE_REPLY RPL_{STORED,NOT_STORED,EXISTS,NOT_FOUND}
+ * STATE_DONE RPL_{STORED,NOT_STORED,EXISTS,NOT_FOUND}
+ *
+ * STATE_ERROR RPL_{ERROR,CLIENT_ERROR,SERVER_ERROR}
+ *
*/
-struct memcache_req *memcache_store (struct memcache *mc, enum memcache_command cmd, const struct memcache_key *key, const struct memcache_obj *obj, void *cb_arg);
+struct memcache_req *memcache_store (struct memcache *mc, enum memcache_command cmd, const struct memcache_key *key, const struct memcache_obj *obj, const struct memcache_buf *buf, void *cb_arg);
/*
- * Request state
+ * Request state.
+ *
+ * Should always return a valid value.
*/
enum memcache_req_state memcache_req_state (struct memcache_req *req);
/*
- * Request key
+ * Request command.
+ *
+ * Should always return a valid value.
*/
-int memcache_req_key (struct memcache_req *req, const struct memcache_key *key);
+enum memcache_command memcache_req_cmd (struct memcache_req *req);
/*
- * Request data
+ * Request reply.
+ *
+ * Will return a valid value in the STATE_REPLY, STATE_REPLY_DATA, STATE_DONE and STATE_DATA_DONE states.
*/
-int memcache_req_obj (struct memcache_req *req, const struct memcache_obj *obj);
+enum memcache_reply memcache_req_reply (struct memcache_req *req);
+
+/*
+ * Request key.
+ *
+ * Will return a valid valuein all states
+ */
+const struct memcache_key *keymemcache_req_key (struct memcache_req *req);
+
+/*
+ * Request data.
+ *
+ * Will return a valid value in the STATE_REPLY, STATE_REPLY_DATA, STATE_DONE and STATE_DATA_DONE states.
+ */
+const struct memcache_obj *memcache_req_obj (struct memcache_req *req);
+
+/*
+ * Request buf.
+ *
+ * Will return a valid value in the STATE_REPLY_DATA and STATE_DATA_DONE states.
+ *
+ * Note that buf.offset may be less than buf.len in the STATE_REPLY_DATA state.
+ */
+const struct memcache_buf *memcache_req_buf (struct memcache_req *req);
+
+/*
+ * Free a req that is in the STATE_DONE, STATE_DATA_DONE or STATE_ERROR state.
+ */
+void memcache_req_free (struct memcache_req *req);
#endif /* MEMCACHE_H */