memcache.h
changeset 44 03a7e064f833
parent 43 e5b714190dee
child 45 10d514029c64
--- 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 */